use std::collections::BTreeMap;
use crate::core::{EffectKey, Seq};
use crate::journal::{Record, RecordKind};
use super::{Completion, ModelId};
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub struct ModelTurn {
pub seq: Seq,
pub key: EffectKey,
pub model: ModelId,
pub completion: Option<Completion>,
}
#[must_use]
pub fn turns(history: &[Record]) -> Vec<ModelTurn> {
let mut asked: BTreeMap<EffectKey, ModelId> = BTreeMap::new();
let mut turns = Vec::new();
for record in history {
let Some(key) = record.effect_key() else {
continue;
};
match record.kind() {
RecordKind::EffectStarted { descriptor, .. } if descriptor.kind == "model.complete" => {
let field = |name: &str| {
descriptor
.args
.get(name)
.and_then(serde_json::Value::as_str)
.unwrap_or_default()
.to_owned()
};
asked.insert(key, ModelId::new(field("provider"), field("model")));
}
RecordKind::EffectDone { output, .. } => {
if let Some(model) = asked.remove(&key) {
turns.push(ModelTurn {
seq: record.seq(),
key,
model,
completion: serde_json::from_value(output.clone()).ok(),
});
}
}
_ => {}
}
}
turns
}