lash_remote_protocol/protocol/
usage_activity.rs1#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
2pub struct RemoteUsage {
3 pub input_tokens: i64,
4 pub output_tokens: i64,
5 pub cache_read_input_tokens: i64,
6 pub cache_write_input_tokens: i64,
7 pub reasoning_output_tokens: i64,
8}
9
10impl RemoteUsage {
11 pub fn add(&mut self, other: &Self) {
12 self.input_tokens += other.input_tokens;
13 self.output_tokens += other.output_tokens;
14 self.cache_read_input_tokens += other.cache_read_input_tokens;
15 self.cache_write_input_tokens += other.cache_write_input_tokens;
16 self.reasoning_output_tokens += other.reasoning_output_tokens;
17 }
18}
19
20#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
21pub struct RemoteTokenLedgerEntry {
22 pub source: String,
23 pub model: String,
24 pub usage: RemoteUsage,
25}
26
27#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
28pub struct RemoteTurnActivity {
29 pub protocol_version: u32,
30 pub sequence: u64,
31 pub id: String,
32 pub correlation_id: String,
33 #[serde(flatten)]
34 pub event: RemoteTurnEvent,
35}
36
37impl RemoteTurnActivity {
38 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
39 ensure_protocol_version(self.protocol_version)?;
40 require_non_empty("RemoteTurnActivity", "id", &self.id)?;
41 require_non_empty("RemoteTurnActivity", "correlation_id", &self.correlation_id)
42 }
43}
44
45#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
46#[serde(tag = "type", rename_all = "snake_case")]
47pub enum RemoteTurnEvent {
48 ModelRequestStarted {
49 protocol_iteration: usize,
50 },
51 AssistantProseDelta {
52 text: String,
53 },
54 ReasoningDelta {
55 text: String,
56 },
57 CodeBlockStarted {
58 language: String,
59 code: String,
60 #[serde(default, skip_serializing_if = "Option::is_none")]
61 graph_key: Option<String>,
62 },
63 CodeBlockCompleted {
64 language: String,
65 output: String,
66 #[serde(default, skip_serializing_if = "Option::is_none")]
67 error: Option<String>,
68 success: bool,
69 duration_ms: u64,
70 tool_call_ids: Vec<String>,
71 #[serde(default, skip_serializing_if = "Option::is_none")]
72 graph_key: Option<String>,
73 },
74 ToolCallStarted {
75 #[serde(default, skip_serializing_if = "Option::is_none")]
76 call_id: Option<String>,
77 name: String,
78 args: serde_json::Value,
79 },
80 ToolCallCompleted {
81 #[serde(default, skip_serializing_if = "Option::is_none")]
82 call_id: Option<String>,
83 name: String,
84 args: serde_json::Value,
85 output: serde_json::Value,
86 duration_ms: u64,
87 },
88 FinalValue {
89 value: serde_json::Value,
90 },
91 ToolValue {
92 tool_name: String,
93 value: serde_json::Value,
94 },
95 Usage {
96 protocol_iteration: usize,
97 usage: RemoteUsage,
98 cumulative: RemoteUsage,
99 },
100 ChildUsage {
101 session_id: String,
102 source: String,
103 model: String,
104 protocol_iteration: usize,
105 usage: RemoteUsage,
106 cumulative: RemoteUsage,
107 },
108 RetryStatus {
109 wait_seconds: u64,
110 attempt: usize,
111 max_attempts: usize,
112 reason: String,
113 },
114 RuntimeDiagnostic {
115 kind: String,
116 data: serde_json::Value,
117 },
118 Error {
119 message: String,
120 },
121}