use kernel::{AxError, EventDraft, EventKind, EventRef, Ledger, Payload, RunId, TimeMs};
#[derive(Debug, Clone, Copy)]
pub(super) enum Authored {
PromptAssembled,
ModelCalled {
at: TimeMs,
},
CancelReceived,
SteerReceived,
}
#[derive(Debug, Clone, Copy)]
pub(super) enum Carried {
ModelReturned { at: TimeMs },
ToolCalled { at: TimeMs },
ToolResult { at: TimeMs },
}
impl Authored {
fn kind(self) -> EventKind {
match self {
Authored::PromptAssembled => EventKind::PromptAssembled,
Authored::ModelCalled { .. } => EventKind::ModelCalled,
Authored::CancelReceived => EventKind::CancelReceived,
Authored::SteerReceived => EventKind::SteerReceived,
}
}
fn at(self, turn: TimeMs) -> TimeMs {
match self {
Authored::ModelCalled { at } => at,
Authored::PromptAssembled | Authored::CancelReceived | Authored::SteerReceived => turn,
}
}
}
impl Carried {
fn kind(self) -> EventKind {
match self {
Carried::ModelReturned { .. } => EventKind::ModelReturned,
Carried::ToolCalled { .. } => EventKind::ToolCalled,
Carried::ToolResult { .. } => EventKind::ToolResult,
}
}
fn at(self) -> TimeMs {
match self {
Carried::ModelReturned { at }
| Carried::ToolCalled { at }
| Carried::ToolResult { at } => at,
}
}
}
pub(super) struct Journal<'h> {
run: RunId,
who: String,
t: TimeMs,
now: &'h mut dyn FnMut() -> Result<TimeMs, AxError>,
refs: Vec<EventRef>,
redacted: u32,
}
impl std::fmt::Debug for Journal<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Journal")
.field("run", &self.run)
.field("who", &self.who)
.field("t", &self.t)
.field("refs", &self.refs)
.field("redacted", &self.redacted)
.finish_non_exhaustive()
}
}
impl<'h> Journal<'h> {
pub(super) fn open(
run: RunId,
who: String,
t: TimeMs,
now: &'h mut dyn FnMut() -> Result<TimeMs, AxError>,
) -> Journal<'h> {
Journal {
run,
who,
t,
now,
refs: Vec::new(),
redacted: 0,
}
}
pub(super) fn redacted(&self) -> u32 {
self.redacted
}
pub(super) fn take_refs(&mut self) -> Vec<EventRef> {
let mut refs = std::mem::take(&mut self.refs);
refs.shrink_to_fit();
refs
}
pub(super) fn append_authored(
&mut self,
ledger: &mut dyn Ledger,
event: Authored,
data: Payload,
) -> Result<EventRef, AxError> {
let at = event.at(self.t);
self.append(ledger, event.kind(), at, data)
}
pub(super) fn append_redacted(
&mut self,
ledger: &mut dyn Ledger,
event: Carried,
data: Payload,
) -> Result<EventRef, AxError> {
let (scanned, hits) = crate::redact::redact(data.as_map());
self.redacted = self.redacted.saturating_add(hits);
self.append(ledger, event.kind(), event.at(), Payload::new(scanned)?)
}
pub(super) fn stamp(&self) -> TimeMs {
self.t
}
pub(super) fn read_clock(&mut self) -> Result<TimeMs, AxError> {
(self.now)()
}
fn append(
&mut self,
ledger: &mut dyn Ledger,
kind: EventKind,
at: TimeMs,
data: Payload,
) -> Result<EventRef, AxError> {
let echo = ledger.append(EventDraft {
run: self.run,
t: at,
who: self.who.clone(),
addr: None,
kind,
data,
ig: false,
})?;
self.refs.push(echo);
Ok(echo)
}
}