Skip to main content

lash_remote_protocol/protocol/
usage_activity.rs

1#[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}