mirror of
https://github.com/openai/codex.git
synced 2026-11-10 21:00:47 +00:00
## Why Asynchronous Guardian collection applied entry caps and compressed heartbeat messages before request preparation, while synchronous collection preserved originals. Preserve the captured evidence so request-time profiles and budgeting determine what is delivered. ## What changed - Replace `prepare_sync_context` with a shared `prepare_context` entry point for synchronous and asynchronous presentations. - Defer text caps, native-message omission, and heartbeat compression to preparation, preserving heartbeat reference numbering across transcript deltas. - Support elastic transcript preparation for both reviewer profiles. - Borrow collected asynchronous context instead of cloning the full transcript, and filter previous reviews against reviewer history during preparation. ## Testing Add coverage for collection preserving originals, fixed preparation truncating text and omitting oversized native entries, and elastic preparation deferring entry caps for both profiles. Update heartbeat tests to cover full and delta preparation without mutating collected evidence. GitOrigin-RevId: 4d4e448acf5dc8880a05c3c9a9754378135f61eb
93 lines
3.7 KiB
Rust
93 lines
3.7 KiB
Rust
//! Structured transcript evidence shared by synchronous and asynchronous Guardian.
|
|
//!
|
|
//! Entry kinds preserve source attribution for consumer-specific retention and
|
|
//! rendering. Both consumers keep originals until request preparation applies caps.
|
|
//! Original sizes remain available for accounting.
|
|
|
|
/// Semantic role of one parent-conversation transcript entry.
|
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
pub enum ConversationTranscriptEntryKind {
|
|
/// Actual parent-thread user message.
|
|
User,
|
|
/// Explicit developer message preserving a user-approved action.
|
|
Developer,
|
|
/// Assistant commentary or an inter-agent message.
|
|
Assistant,
|
|
/// Final assistant answer eligible for stronger async retention.
|
|
ProtectedAssistant,
|
|
/// Named tool invocation, including shell and web-search calls.
|
|
ToolCall(String),
|
|
/// Tool result with a call-derived, explicit, or generic fallback label.
|
|
ToolOutput(String),
|
|
/// Result from a Node REPL-backed tool that may receive a larger sync cap.
|
|
NodeReplToolOutput(String),
|
|
/// Plaintext model reasoning that the async consumer explicitly enables.
|
|
Reasoning,
|
|
}
|
|
|
|
impl ConversationTranscriptEntryKind {
|
|
/// Returns the role label currently used in Guardian transcript prompts.
|
|
pub fn role(&self) -> &str {
|
|
match self {
|
|
Self::User => "user",
|
|
Self::Developer => "developer",
|
|
Self::Assistant | Self::ProtectedAssistant => "assistant",
|
|
Self::ToolCall(role) | Self::ToolOutput(role) | Self::NodeReplToolOutput(role) => {
|
|
role.as_str()
|
|
}
|
|
Self::Reasoning => "reasoning",
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Collected text, a host-attributed record, or an opaque backend-native message.
|
|
#[derive(Clone, PartialEq)]
|
|
pub enum TranscriptContent {
|
|
Text(String),
|
|
/// Original scheduler input, compressed only during request preparation.
|
|
ScheduledMessage(ScheduledTranscriptMessage),
|
|
/// Host-attributed text prepared by the profile, rendered at delivery.
|
|
Record(crate::TranscriptRecord),
|
|
NativeMessage(Box<codex_protocol::models::ResponseItem>),
|
|
}
|
|
|
|
impl std::fmt::Debug for TranscriptContent {
|
|
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
formatter.write_str(match self {
|
|
Self::Text(_) => "Text(..)",
|
|
Self::ScheduledMessage(_) => "ScheduledMessage(..)",
|
|
Self::Record(_) => "Record(..)",
|
|
Self::NativeMessage(_) => "NativeMessage(..)",
|
|
})
|
|
}
|
|
}
|
|
|
|
/// Structured evidence shared by sync Guardian and async scoring.
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
pub struct ConversationTranscriptEntry {
|
|
/// Semantic role used for consumer-specific retention and truncation.
|
|
pub kind: ConversationTranscriptEntryKind,
|
|
/// Original captured evidence, or content bounded during preparation.
|
|
pub content: TranscriptContent,
|
|
/// Size before truncation, retained for omission and truncation accounting.
|
|
pub original_bytes: usize,
|
|
/// Original source revision and display order, established from host metadata.
|
|
pub retained_source: Option<RetainedTranscriptSource>,
|
|
}
|
|
|
|
/// Display ordering is separate from source identity and cannot establish delivery.
|
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
pub struct RetainedTranscriptSource {
|
|
/// Size of the complete role- and order-labeled source, before request admission.
|
|
pub rendered_bytes: usize,
|
|
pub order: String,
|
|
pub source: codex_history::RetainedSource,
|
|
}
|
|
|
|
/// Original scheduler text and the provenance needed to compare heartbeat instructions.
|
|
#[derive(Clone, PartialEq)]
|
|
pub struct ScheduledTranscriptMessage {
|
|
pub(crate) text: String,
|
|
pub(crate) heartbeat: Option<crate::preparation::HeartbeatInstruction>,
|
|
}
|