use crate::ids::{ModelId, ModelVersion, SessionId};
use crate::value_objects::{
DeviceTarget, ModelFormat, RuntimeKind, SafetyMode, SpeculationMode, StopReason,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DegradeReason {
Disabled,
MemoryPressure,
MidRangeProfile,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DomainEvent {
SessionInitialized {
runtime: RuntimeKind,
device: DeviceTarget,
safety: SafetyMode,
speculation: SpeculationMode,
},
ModelLoaded {
model: ModelId,
version: ModelVersion,
format: ModelFormat,
},
PrefillCompleted {
prompt_tokens: u32,
kv_len: u32,
prefill_tps: u32,
},
TokenGenerated {
sampled: bool,
},
TokenCommitted {
kv_len: u32,
},
GenerationCompleted {
total_tokens: u32,
stop: StopReason,
},
SessionReset,
HybridRelayConsulted,
PromptCompressed {
input_tokens: u32,
output_tokens: u32,
ratio_milli: u32,
},
CompressionSkipped {
reason: DegradeReason,
},
DraftProposed {
draft_len: u8,
},
DraftVerified {
accepted: u8,
first_reject: u8,
},
SpeculationDisabled {
reason: DegradeReason,
},
GrammarSwitched {
from_state: u32,
to_state: u32,
},
TokenMaskApplied {
allowed: u32,
},
GrammarViolationBlocked,
SafetyModeSelected {
mode: SafetyMode,
},
LogitsSteered {
adjustment_norm_milli: u32,
},
SafetyViolationDetected {
score_milli: u16,
threshold_milli: u16,
},
ClaimBacktracked {
claim_index: u32,
},
SafetyDisabled {
reason: DegradeReason,
},
MemoryPlanCreated {
total_bytes: u64,
sram_bytes: u64,
dram_bytes: u64,
},
KvCacheCompacted {
reclaimed: u32,
},
MemoryBudgetExceeded {
requested_bytes: u64,
budget_bytes: u64,
},
DeviceProfiled {
profile: DeviceTarget,
npu_tops: u16,
bandwidth_gbs: u16,
},
DelegateSelected {
partitions: u8,
},
DelegateFellBack,
ModelSignatureVerified {
model: ModelId,
version: ModelVersion,
},
ModelSignatureRejected {
model: ModelId,
},
MetricsSampled {
decode_tps: u32,
ttft_ms: u32,
peak_bytes: u64,
},
FrontierLlmConsulted {
provider_hash: u32,
prompt_tokens: u32,
completion_tokens: u32,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct EventEnvelope {
pub session: SessionId,
pub step: u32,
pub event: DomainEvent,
}
impl EventEnvelope {
pub fn new(session: SessionId, step: u32, event: DomainEvent) -> Self {
Self {
session,
step,
event,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn _assert_copy<T: Copy>() {}
#[test]
fn events_are_content_free_by_construction() {
_assert_copy::<DomainEvent>();
_assert_copy::<EventEnvelope>();
}
#[test]
fn envelope_carries_step_and_session() {
let e = EventEnvelope::new(
SessionId(1),
4,
DomainEvent::TokenGenerated { sampled: true },
);
assert_eq!(e.step, 4);
assert_eq!(e.session, SessionId(1));
}
}