mirror of
https://github.com/openai/codex.git
synced 2026-11-03 19:53:25 +00:00
Consolidate guardian transcript tests in guardian-context (#45683)
## What changed Remove core guardian tests for transcript numbering and unpaired tool outputs. Extend `guardian-context` coverage to assert that named image-only tool outputs retain their source and use `[non-text output]` for both sync and async contexts, with tool calls included or excluded. GitOrigin-RevId: ba483e8f6e335697106a987051687a12ad2fde01
This commit is contained in:
@@ -44,8 +44,6 @@ use codex_protocol::approvals::NetworkApprovalProtocol;
|
||||
use codex_protocol::config_types::ApprovalsReviewer;
|
||||
use codex_protocol::config_types::ReasoningSummary;
|
||||
use codex_protocol::models::ContentItem;
|
||||
use codex_protocol::models::FunctionCallOutputContentItem;
|
||||
use codex_protocol::models::ImageReference;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use codex_protocol::models::SandboxPermissions;
|
||||
@@ -399,38 +397,6 @@ fn last_user_message_text_from_body(body: &serde_json::Value) -> String {
|
||||
.collect::<String>()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_guardian_transcript_keeps_original_numbering() {
|
||||
let entries = [
|
||||
ConversationTranscriptEntry {
|
||||
kind: ConversationTranscriptEntryKind::User,
|
||||
text: "first".to_string(),
|
||||
original_bytes: "first".len(),
|
||||
},
|
||||
ConversationTranscriptEntry {
|
||||
kind: ConversationTranscriptEntryKind::Assistant,
|
||||
text: "second".to_string(),
|
||||
original_bytes: "second".len(),
|
||||
},
|
||||
ConversationTranscriptEntry {
|
||||
kind: ConversationTranscriptEntryKind::ProtectedAssistant,
|
||||
text: "third".to_string(),
|
||||
original_bytes: "third".len(),
|
||||
},
|
||||
];
|
||||
|
||||
let (transcript, omission) = render_guardian_transcript_entries(&entries[..2]);
|
||||
|
||||
assert_eq!(
|
||||
transcript,
|
||||
vec![
|
||||
"[1] user: first".to_string(),
|
||||
"[2] assistant: second".to_string()
|
||||
]
|
||||
);
|
||||
assert!(omission.is_none());
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn build_guardian_prompt_full_mode_preserves_initial_review_format() -> anyhow::Result<()> {
|
||||
let (session, turn) = guardian_test_session_and_turn_with_base_url("http://localhost").await;
|
||||
@@ -1071,86 +1037,6 @@ fn collect_guardian_transcript_entries_includes_recent_tool_calls_and_output() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn collect_guardian_transcript_entries_preserves_named_unpaired_tool_sources() {
|
||||
let mut items = vec![ResponseItem::FunctionCallOutput {
|
||||
id: None,
|
||||
call_id: None,
|
||||
name: Some("notifications".to_string()),
|
||||
namespace: Some("slack".to_string()),
|
||||
output: codex_protocol::models::FunctionCallOutputPayload::from_text(
|
||||
"new message".to_string(),
|
||||
),
|
||||
internal_chat_message_metadata_passthrough: None,
|
||||
}];
|
||||
items.extend(
|
||||
[
|
||||
(None, "anonymous output"),
|
||||
(Some("missing-call"), "orphaned function output"),
|
||||
]
|
||||
.map(|(call_id, text)| ResponseItem::FunctionCallOutput {
|
||||
id: None,
|
||||
call_id: call_id.map(str::to_string),
|
||||
name: None,
|
||||
namespace: None,
|
||||
output: codex_protocol::models::FunctionCallOutputPayload::from_text(text.to_string()),
|
||||
internal_chat_message_metadata_passthrough: None,
|
||||
}),
|
||||
);
|
||||
items.push(ResponseItem::CustomToolCallOutput {
|
||||
id: None,
|
||||
call_id: "missing-custom-call".to_string(),
|
||||
name: None,
|
||||
output: codex_protocol::models::FunctionCallOutputPayload::from_text(
|
||||
"orphaned custom output".to_string(),
|
||||
),
|
||||
internal_chat_message_metadata_passthrough: None,
|
||||
});
|
||||
|
||||
let mut expected = vec![ConversationTranscriptEntry {
|
||||
kind: ConversationTranscriptEntryKind::ToolOutput(
|
||||
"tool slack.notifications result".to_string(),
|
||||
),
|
||||
text: "new message".to_string(),
|
||||
original_bytes: "new message".len(),
|
||||
}];
|
||||
expected.extend(
|
||||
["orphaned function output", "orphaned custom output"].map(|text| {
|
||||
ConversationTranscriptEntry {
|
||||
kind: ConversationTranscriptEntryKind::ToolOutput("tool result".to_string()),
|
||||
text: text.to_string(),
|
||||
original_bytes: text.len(),
|
||||
}
|
||||
}),
|
||||
);
|
||||
assert_eq!(
|
||||
collect_guardian_transcript_entries(&items, GUARDIAN_MAX_TOOL_ENTRY_TOKENS),
|
||||
expected,
|
||||
);
|
||||
|
||||
if let ResponseItem::FunctionCallOutput { output, .. } = &mut items[0] {
|
||||
*output = codex_protocol::models::FunctionCallOutputPayload::from_content_items(vec![
|
||||
FunctionCallOutputContentItem::InputImage {
|
||||
image: ImageReference::Inline {
|
||||
image_url: "data:image/png;base64,image".to_string(),
|
||||
},
|
||||
detail: None,
|
||||
},
|
||||
]);
|
||||
}
|
||||
expected[0] = ConversationTranscriptEntry {
|
||||
kind: ConversationTranscriptEntryKind::ToolOutput(
|
||||
"tool slack.notifications result".to_string(),
|
||||
),
|
||||
text: "[non-text output]".to_string(),
|
||||
original_bytes: "[non-text output]".len(),
|
||||
};
|
||||
assert_eq!(
|
||||
collect_guardian_transcript_entries(&items, GUARDIAN_MAX_TOOL_ENTRY_TOKENS),
|
||||
expected,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn guardian_truncate_text_keeps_prefix_suffix_and_xml_marker() {
|
||||
let content = "prefix ".repeat(200) + &" suffix".repeat(200);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
use codex_protocol::models::ContentItem;
|
||||
use codex_protocol::models::FunctionCallOutputContentItem;
|
||||
use codex_protocol::models::FunctionCallOutputPayload;
|
||||
use codex_protocol::models::ImageReference;
|
||||
use codex_protocol::models::LocalShellAction;
|
||||
use codex_protocol::models::LocalShellExecAction;
|
||||
use codex_protocol::models::LocalShellStatus;
|
||||
@@ -241,6 +243,21 @@ fn outputs_with_call_ids_or_explicit_names_are_retained() {
|
||||
Some("notifications"),
|
||||
"named notification",
|
||||
),
|
||||
ResponseItem::FunctionCallOutput {
|
||||
id: None,
|
||||
call_id: None,
|
||||
name: Some("notifications".to_string()),
|
||||
namespace: Some("slack".to_string()),
|
||||
output: FunctionCallOutputPayload::from_content_items(vec![
|
||||
FunctionCallOutputContentItem::InputImage {
|
||||
image: ImageReference::Inline {
|
||||
image_url: "data:image/png;base64,image".to_string(),
|
||||
},
|
||||
detail: None,
|
||||
},
|
||||
]),
|
||||
internal_chat_message_metadata_passthrough: None,
|
||||
},
|
||||
output(
|
||||
Some("missing-call"),
|
||||
Some("notifications"),
|
||||
@@ -290,6 +307,12 @@ fn outputs_with_call_ids_or_explicit_names_are_retained() {
|
||||
let mut expected = vec![
|
||||
generic("orphaned function output"),
|
||||
named.clone(),
|
||||
entry(
|
||||
ConversationTranscriptEntryKind::ToolOutput(
|
||||
"tool slack.notifications result".to_string(),
|
||||
),
|
||||
"[non-text output]",
|
||||
),
|
||||
generic("named orphaned function output"),
|
||||
generic("orphaned custom output"),
|
||||
generic("named orphaned custom output"),
|
||||
|
||||
Reference in New Issue
Block a user