#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteUsage {
pub input_tokens: i64,
pub output_tokens: i64,
pub cached_input_tokens: i64,
#[serde(default)]
pub reasoning_tokens: i64,
}
impl RemoteUsage {
pub fn add(&mut self, other: &Self) {
self.input_tokens += other.input_tokens;
self.output_tokens += other.output_tokens;
self.cached_input_tokens += other.cached_input_tokens;
self.reasoning_tokens += other.reasoning_tokens;
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteTokenLedgerEntry {
pub source: String,
pub model: String,
pub usage: RemoteUsage,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteTurnActivity {
pub protocol_version: u32,
pub sequence: u64,
pub id: String,
pub correlation_id: String,
#[serde(flatten)]
pub event: RemoteTurnEvent,
}
impl RemoteTurnActivity {
pub fn validate(&self) -> Result<(), RemoteProtocolError> {
ensure_protocol_version(self.protocol_version)?;
require_non_empty("RemoteTurnActivity", "id", &self.id)?;
require_non_empty("RemoteTurnActivity", "correlation_id", &self.correlation_id)
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum RemoteTurnEvent {
ModelRequestStarted {
protocol_iteration: usize,
},
AssistantProseDelta {
text: String,
},
ReasoningDelta {
text: String,
},
CodeBlockStarted {
language: String,
code: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
graph_key: Option<String>,
},
CodeBlockCompleted {
language: String,
output: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
error: Option<String>,
success: bool,
duration_ms: u64,
tool_call_ids: Vec<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
graph_key: Option<String>,
},
ToolCallStarted {
#[serde(default, skip_serializing_if = "Option::is_none")]
call_id: Option<String>,
name: String,
args: serde_json::Value,
},
ToolCallCompleted {
#[serde(default, skip_serializing_if = "Option::is_none")]
call_id: Option<String>,
name: String,
args: serde_json::Value,
output: serde_json::Value,
duration_ms: u64,
},
SubmittedValue {
value: serde_json::Value,
},
ToolValue {
tool_name: String,
value: serde_json::Value,
},
Usage {
protocol_iteration: usize,
usage: RemoteUsage,
cumulative: RemoteUsage,
},
ChildUsage {
session_id: String,
source: String,
model: String,
protocol_iteration: usize,
usage: RemoteUsage,
cumulative: RemoteUsage,
},
RetryStatus {
wait_seconds: u64,
attempt: usize,
max_attempts: usize,
reason: String,
},
RuntimeDiagnostic {
kind: String,
data: serde_json::Value,
},
Error {
message: String,
},
}