(
block: &SessionBlock,
token_limit: Option<&str>,
max_tokens: u64,
)
| 146 | } |
| 147 | |
| 148 | pub(crate) fn block_json( |
| 149 | block: &SessionBlock, |
| 150 | token_limit: Option<&str>, |
| 151 | max_tokens: u64, |
| 152 | ) -> Value { |
| 153 | let burn_rate = if block.is_active { |
| 154 | calculate_burn_rate(block) |
| 155 | } else { |
| 156 | None |
| 157 | }; |
| 158 | let projection = if block.is_active { |
| 159 | project_block_usage(block) |
| 160 | } else { |
| 161 | None |
| 162 | }; |
| 163 | let token_limit_status = projection.and_then(|projection| { |
| 164 | let limit = token_limit.and_then(|_| parse_token_limit(token_limit, max_tokens))?; |
| 165 | let percent = projection.total_tokens as f64 / limit as f64 * 100.0; |
| 166 | Some(json!({ |
| 167 | "limit": limit, |
| 168 | "projectedUsage": projection.total_tokens, |
| 169 | "percentUsed": percent, |
| 170 | "status": if projection.total_tokens > limit { "exceeds" } else if projection.total_tokens as f64 > limit as f64 * BLOCKS_WARNING_THRESHOLD { "warning" } else { "ok" }, |
| 171 | })) |
| 172 | }); |
| 173 | let mut value = json!({ |
| 174 | "id": block.id, |
| 175 | "startTime": format_rfc3339_millis(block.start_time), |
| 176 | "endTime": format_rfc3339_millis(block.end_time), |
| 177 | "actualEndTime": block.actual_end_time.map(format_rfc3339_millis), |
| 178 | "isActive": block.is_active, |
| 179 | "isGap": block.is_gap, |
| 180 | "entries": block.entries.len(), |
| 181 | "tokenCounts": { |
| 182 | "inputTokens": block.token_counts.input_tokens, |
| 183 | "outputTokens": block.token_counts.output_tokens, |
| 184 | "cacheCreationInputTokens": block.token_counts.cache_creation_tokens, |
| 185 | "cacheReadInputTokens": block.token_counts.cache_read_tokens, |
| 186 | }, |
| 187 | "totalTokens": block.token_counts.total(), |
| 188 | "costUSD": json_float(block.cost_usd), |
| 189 | "models": block.models, |
| 190 | "burnRate": burn_rate, |
| 191 | "projection": projection, |
| 192 | }); |
| 193 | if let Some(status) = token_limit_status { |
| 194 | value["tokenLimitStatus"] = status; |
| 195 | } |
| 196 | if let Some(reset_time) = block.usage_limit_reset_time { |
| 197 | value["usageLimitResetTime"] = json!(format_rfc3339_millis(reset_time)); |
| 198 | } |
| 199 | value |
| 200 | } |
| 201 | |
| 202 | fn format_block_models(models: &[String]) -> String { |
| 203 | if models.is_empty() { |
nothing calls this directly
no test coverage detected