mirror of
https://github.com/openai/codex.git
synced 2026-10-21 07:42:01 +00:00
Assign stable IDs to generated Responses input items (#41349)
## What changed - Assign type-prefixed IDs to Guardian classifier input items before sending the request, preserving existing IDs and reusing generated IDs across WebSocket retries. - Add a prefixed ID to the memory phase-one user message. ## Testing - Verify retried Guardian requests contain the same unique, prefixed item IDs. - Verify the memory phase-one request includes a prefixed user-message ID. GitOrigin-RevId: e01da49d9a661b6bfd2088f091a3ddf69d601e40
This commit is contained in:
@@ -1208,6 +1208,7 @@ classifier_instructions = "Predict future violations.\n# Security Policy\n{{ ten
|
||||
request["input"][1],
|
||||
json!({
|
||||
"type": "message",
|
||||
"id": request["input"][1]["id"],
|
||||
"role": "developer",
|
||||
"content": [{
|
||||
"type": "input_text",
|
||||
@@ -1246,6 +1247,7 @@ max_classifier_instruction_tokens = 256
|
||||
request["input"][1],
|
||||
json!({
|
||||
"type": "message",
|
||||
"id": request["input"][1]["id"],
|
||||
"role": "developer",
|
||||
"content": [{
|
||||
"type": "input_text",
|
||||
@@ -1334,6 +1336,7 @@ max_recent_non_user_entries = 8
|
||||
request["input"][1],
|
||||
json!({
|
||||
"type": "message",
|
||||
"id": request["input"][1]["id"],
|
||||
"role": "developer",
|
||||
"content": [{
|
||||
"type": "input_text",
|
||||
@@ -1735,6 +1738,7 @@ async fn contributor_uses_model_defaults_and_preserves_local_overrides() -> Resu
|
||||
request["input"][1],
|
||||
json!({
|
||||
"type": "message",
|
||||
"id": request["input"][1]["id"],
|
||||
"role": "developer",
|
||||
"content": [{
|
||||
"type": "input_text",
|
||||
@@ -1900,6 +1904,7 @@ async fn contributor_samples_tool_calls_with_the_existing_luna_pool() -> Result<
|
||||
request["input"][1],
|
||||
json!({
|
||||
"type": "message",
|
||||
"id": request["input"][1]["id"],
|
||||
"role": "developer",
|
||||
"content": [{
|
||||
"type": "input_text",
|
||||
@@ -2321,6 +2326,7 @@ async fn contributor_uses_catalog_policy_without_a_configured_override() -> Resu
|
||||
request["input"][1],
|
||||
json!({
|
||||
"type": "message",
|
||||
"id": request["input"][1]["id"],
|
||||
"role": "developer",
|
||||
"content": [{
|
||||
"type": "input_text",
|
||||
@@ -2363,6 +2369,7 @@ async fn contributor_preserves_uncapped_classifier_instructions() -> Result<()>
|
||||
request["input"][1],
|
||||
json!({
|
||||
"type": "message",
|
||||
"id": request["input"][1]["id"],
|
||||
"role": "developer",
|
||||
"content": [{
|
||||
"type": "input_text",
|
||||
|
||||
@@ -29,6 +29,7 @@ use codex_login::default_client::default_headers;
|
||||
use codex_model_provider::AgentIdentitySessionFallback;
|
||||
use codex_model_provider::ProviderAuthScope;
|
||||
use codex_model_provider::SharedModelProvider;
|
||||
use codex_protocol::ResponseItemId;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::error::CodexErr;
|
||||
use codex_protocol::models::ContentItem;
|
||||
@@ -504,6 +505,14 @@ impl LunaSampler {
|
||||
phase: None,
|
||||
internal_chat_message_metadata_passthrough: None,
|
||||
});
|
||||
// Assign IDs once so retries reuse the same input item identities.
|
||||
for item in &mut input {
|
||||
if item.id().is_none()
|
||||
&& let Some(prefix) = item.id_prefix()
|
||||
{
|
||||
item.set_id(Some(ResponseItemId::new(prefix)));
|
||||
}
|
||||
}
|
||||
let mut request = ResponsesApiRequest {
|
||||
model: MODEL.to_owned(),
|
||||
instructions: String::new(),
|
||||
|
||||
@@ -904,7 +904,10 @@ async fn sampler_retries_expired_websockets_on_another_warm_connection() -> Resu
|
||||
))
|
||||
.await?;
|
||||
|
||||
let output = sampler.sample(sample_request("turn-1")).await?;
|
||||
let mut request = sample_request("turn-1");
|
||||
request.trusted_review_evidence = vec!["trusted review".to_owned()];
|
||||
request.trusted_skill_paths = vec!["/skills/review/SKILL.md".to_owned()];
|
||||
let output = sampler.sample(request).await?;
|
||||
|
||||
assert_eq!(output, "low");
|
||||
let expired_requests = expired.single_connection();
|
||||
@@ -925,6 +928,13 @@ async fn sampler_retries_expired_websockets_on_another_warm_connection() -> Resu
|
||||
.remove("client_metadata");
|
||||
}
|
||||
assert_eq!(expired_request, healthy_request);
|
||||
let input: Vec<ResponseItem> = serde_json::from_value(healthy_request["input"].clone())?;
|
||||
let ids = input
|
||||
.iter()
|
||||
.map(|item| item.id().expect("classifier input item ID"))
|
||||
.collect::<HashSet<_>>();
|
||||
assert_eq!(ids.len(), input.len());
|
||||
assert!(ids.iter().all(|id| id.is_prefixed()));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ use codex_config::types::MemoriesConfig;
|
||||
use codex_core::Prompt;
|
||||
use codex_core::RolloutRecorder;
|
||||
use codex_core::config::Config;
|
||||
use codex_protocol::ResponseItemId;
|
||||
use codex_protocol::error::CodexErr;
|
||||
use codex_protocol::models::BaseInstructions;
|
||||
use codex_protocol::models::ContentItem;
|
||||
@@ -292,7 +293,7 @@ mod job {
|
||||
|
||||
let mut prompt = Prompt::default();
|
||||
prompt.input = vec![ResponseItem::Message {
|
||||
id: None,
|
||||
id: Some(ResponseItemId::new("msg")),
|
||||
role: "user".to_string(),
|
||||
content: vec![ContentItem::InputText {
|
||||
text: build_stage_one_input_message(
|
||||
|
||||
@@ -19,6 +19,7 @@ use codex_model_provider::ProviderAccountResult;
|
||||
use codex_model_provider::SharedModelProvider;
|
||||
use codex_model_provider::create_model_provider;
|
||||
use codex_model_provider_info::ModelProviderInfo;
|
||||
use codex_protocol::ResponseItemId;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::config_types::ServiceTier;
|
||||
use codex_protocol::models::ContentItem;
|
||||
@@ -689,6 +690,12 @@ async fn memories_startup_phase1_provider_default_drives_request_model() -> anyh
|
||||
request.body_json()["model"].as_str(),
|
||||
Some(MOCK_PROVIDER_PHASE_ONE_MODEL)
|
||||
);
|
||||
let input: Vec<ResponseItem> = serde_json::from_value(request.body_json()["input"].clone())?;
|
||||
let message = input
|
||||
.iter()
|
||||
.find(|item| item.is_user_message())
|
||||
.expect("phase-one input message");
|
||||
assert!(message.id().is_some_and(ResponseItemId::is_prefixed));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user