use crate::routing::quota::{billing::BillingState, live};
use crate::store::Store;
use crate::types::{AgentKind, EventKind, TaskEvent, TaskId};
pub(super) fn record(store: &Store, task_id: &TaskId, agent: AgentKind) -> anyhow::Result<()> {
let Some(billing) = live::billing(&agent) else {
return Ok(());
};
if matches!(billing.state, BillingState::Overage | BillingState::Exhausted) {
aid_warn!("[aid] {} billing: {}", agent.as_str(), billing.label());
}
if billing.state != BillingState::Overage {
return Ok(());
}
if store.get_events(task_id.as_str())?.iter().any(|event| {
event
.metadata
.as_ref()
.and_then(|meta| meta.get("billing_state"))
.and_then(serde_json::Value::as_str)
== Some("overage")
}) {
return Ok(());
}
store.insert_event(&TaskEvent {
task_id: task_id.clone(),
timestamp: chrono::Local::now(),
event_kind: EventKind::Setup,
detail: format!("billing: {}", billing.label()),
metadata: Some(serde_json::json!({"billing_state": "overage", "billing": billing})),
})?;
Ok(())
}
#[cfg(test)]
#[path = "billing_tests.rs"]
mod tests;