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