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:
felixxia-oai
2026-09-15 12:14:59 +00:00
committed by copyberry
parent 954fa9057b
commit 709efcb7a9
2 changed files with 23 additions and 114 deletions
-114
View File
@@ -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"),