use super::*;
pub(crate) const EXCERPT_MAX: usize = 400;
pub(crate) const REDACTED_THINKING_PLACEHOLDER: &str = "[redacted thinking]";
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Pairing {
Paired,
PendingNoResult,
OrphanResult,
}
#[derive(Debug, Clone)]
pub struct Hit {
pub class: Class,
pub labels: Vec<&'static str>,
pub excerpt: String,
pub timestamp_utc: Option<String>,
pub tool_name: Option<String>,
pub model: Option<String>,
pub attachment_type: Option<String>,
pub version: Option<String>,
pub is_error: Option<bool>,
pub direction: Option<(String, String)>,
pub tool_use_id: Option<String>,
pub pair: Option<Pairing>,
pub line: usize,
pub uuid: Option<String>,
pub raw: Option<String>,
pub image_ids: Vec<String>,
pub from_sidecar: bool,
pub queue_operation: Option<String>,
pub queue_reason: Option<String>,
pub delivery: Option<bool>,
pub truncated: bool,
}
impl Hit {
#[must_use]
pub fn delivered(&self) -> bool {
self.delivery.unwrap_or_else(|| self.class.llm_visible())
}
}
#[derive(Debug, Clone)]
pub struct DraftDiff {
pub superseding_line: usize,
pub superseding_uuid: Option<String>,
pub chars: usize,
pub pct: Option<f64>,
pub exact: bool,
}
impl DraftDiff {
pub(crate) fn text_line(&self) -> String {
if self.exact && self.chars == 0 {
return "identical to the sent message".to_string();
}
let more = if self.exact { "" } else { "more than " };
match self.pct {
Some(p) => format!(
"differs from the sent message in {more}{} chars ({more}{p:.1}% of the final): \
may carry an addition or a correction",
self.chars
),
None => format!(
"differs from the sent message in {more}{} chars: may carry an addition or a \
correction",
self.chars
),
}
}
pub(crate) fn pct_json(&self) -> serde_json::Value {
match self.pct {
Some(p) => serde_json::json!((p * 10.0).round() / 10.0),
None => serde_json::Value::Null,
}
}
pub(crate) fn attach_json(&self, obj: &mut serde_json::Value) {
obj["superseding_line"] = serde_json::json!(self.superseding_line);
obj["superseding_uuid"] = serde_json::json!(self.superseding_uuid);
obj["diff_chars"] = serde_json::json!(self.chars);
obj["diff_pct"] = self.pct_json();
obj["diff_exact"] = serde_json::json!(self.exact);
}
}
#[derive(Debug, Clone)]
pub struct Exchange {
pub session_id: String,
pub is_subagent: bool,
pub parent_session_id: String,
pub turn_index: usize,
pub started_utc: Option<String>,
pub hits: Vec<Hit>,
pub siblings: Vec<Hit>,
pub siblings_hidden: usize,
pub turn_lines: (usize, usize),
pub record_uuids: Vec<String>,
pub superseded_draft: bool,
pub draft_diff: Option<DraftDiff>,
}
#[derive(Debug, Clone, Default)]
pub struct SearchOutcome {
pub exchanges: Vec<Exchange>,
pub total_matched: usize,
pub total_sessions: usize,
pub dropped_by_cap: usize,
pub skipped_lines: usize,
pub superseded_drafts: usize,
pub scope_top: usize,
pub scope_sub: usize,
}