use polyc_proto::proto::polychrome::events::v1::ModelCallEvent;
#[derive(Debug, Clone, Default, PartialEq)]
pub struct DecodeParamsFact {
pub temperature: Option<f64>,
pub top_p: Option<f64>,
pub max_tokens: Option<u32>,
pub reasoning_level: Option<String>,
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct ModelCallFact {
pub provider: String,
pub model: String,
pub decode_params: DecodeParamsFact,
pub system_config_ref: String,
pub captured_clock_unix_ms: u64,
pub clear_trigger_bytes: u64,
pub clear_keep_recent: u32,
pub clear_marker: String,
pub persona_block_placement_wire: u32,
}
impl From<ModelCallEvent> for ModelCallFact {
fn from(event: ModelCallEvent) -> Self {
let dp = event.decode_params.into_option().unwrap_or_default();
Self {
provider: event.provider,
model: event.model,
decode_params: DecodeParamsFact {
temperature: dp.has_temperature.then_some(dp.temperature),
top_p: dp.has_top_p.then_some(dp.top_p),
max_tokens: dp.has_max_tokens.then_some(dp.max_tokens),
reasoning_level: (!dp.reasoning_level.is_empty()).then_some(dp.reasoning_level),
},
system_config_ref: event.system_config_ref,
captured_clock_unix_ms: event.captured_clock_unix_ms,
clear_trigger_bytes: event.clear_trigger_bytes,
clear_keep_recent: event.clear_keep_recent,
clear_marker: event.clear_marker,
persona_block_placement_wire: event.persona_block_placement,
}
}
}
pub fn fold_model_call_event(payload: &[u8]) -> Result<ModelCallFact, buffa::DecodeError> {
polyc_proto::events_decode::try_decode_event_payload::<ModelCallEvent>(payload)
.map(ModelCallFact::from)
}
#[cfg(test)]
mod tests {
#![allow(clippy::pedantic, clippy::nursery, missing_docs, clippy::unwrap_used)]
use buffa::Message as _;
use polyc_proto::proto::polychrome::events::v1::DecodeParams;
use super::*;
fn full_event() -> ModelCallEvent {
ModelCallEvent {
provider: "vertex".to_owned(),
model: "fable-pro".to_owned(),
decode_params: buffa::MessageField::some(DecodeParams {
has_temperature: true,
temperature: 0.7,
has_top_p: false,
top_p: 0.0,
has_max_tokens: true,
max_tokens: 4096,
reasoning_level: "low".to_owned(),
__buffa_unknown_fields: buffa::UnknownFields::default(),
}),
system_config_ref: "abc123".to_owned(),
captured_clock_unix_ms: 1_700_000_000_123,
clear_trigger_bytes: 4096,
clear_keep_recent: 3,
clear_marker: "-- cleared --".to_owned(),
persona_block_placement: 1,
__buffa_unknown_fields: buffa::UnknownFields::default(),
}
}
#[test]
fn round_trips_every_field() {
let bytes = full_event().encode_to_vec();
let fact = fold_model_call_event(&bytes).expect("decode model_call");
assert_eq!(fact.provider, "vertex");
assert_eq!(fact.model, "fable-pro");
assert_eq!(fact.decode_params.temperature, Some(0.7));
assert_eq!(fact.decode_params.top_p, None, "has_top_p was false");
assert_eq!(fact.decode_params.max_tokens, Some(4096));
assert_eq!(fact.decode_params.reasoning_level.as_deref(), Some("low"));
assert_eq!(fact.system_config_ref, "abc123");
assert_eq!(fact.captured_clock_unix_ms, 1_700_000_000_123);
assert_eq!(fact.clear_trigger_bytes, 4096);
assert_eq!(fact.clear_keep_recent, 3);
assert_eq!(fact.clear_marker, "-- cleared --");
assert_eq!(fact.persona_block_placement_wire, 1);
}
#[test]
fn empty_payload_decodes_to_defaults() {
let fact = fold_model_call_event(&[]).expect("empty payload decodes");
assert_eq!(fact, ModelCallFact::default());
}
#[test]
fn empty_reasoning_level_decodes_to_none() {
let mut event = full_event();
event.decode_params = buffa::MessageField::some(DecodeParams {
has_temperature: true,
temperature: 0.7,
has_top_p: false,
top_p: 0.0,
has_max_tokens: true,
max_tokens: 4096,
reasoning_level: String::new(),
__buffa_unknown_fields: buffa::UnknownFields::default(),
});
let bytes = event.encode_to_vec();
let fact = fold_model_call_event(&bytes).expect("decode");
assert_eq!(fact.decode_params.reasoning_level, None);
}
#[test]
fn garbage_bytes_return_an_error() {
assert!(fold_model_call_event(&[0xFF, 0xFE, 0xFD]).is_err());
}
}