| 194 | } |
| 195 | |
| 196 | fn render_sections( |
| 197 | &self, |
| 198 | frame: &mut Frame, |
| 199 | area: Rect, |
| 200 | theme: &Theme, |
| 201 | state: &mut SidebarState, |
| 202 | floating: bool, |
| 203 | ) { |
| 204 | if area.width == 0 || area.height == 0 { |
| 205 | state.set_sections_layout(area, 0, Vec::new()); |
| 206 | return; |
| 207 | } |
| 208 | |
| 209 | let session_ctx = self.context.session.read(); |
| 210 | let mcp_servers = self.context.mcp_servers.read(); |
| 211 | let lsp_status = self.context.lsp_status.read(); |
| 212 | |
| 213 | let session = session_ctx.sessions.get(&self.session_id); |
| 214 | let messages = session_ctx |
| 215 | .messages |
| 216 | .get(&self.session_id) |
| 217 | .cloned() |
| 218 | .unwrap_or_default(); |
| 219 | |
| 220 | let title = session |
| 221 | .map(|s| s.title.clone()) |
| 222 | .unwrap_or_else(|| "New Session".to_string()); |
| 223 | let mut sections: Vec<SidebarSection> = vec![SidebarSection { |
| 224 | key: "session", |
| 225 | title: "Session", |
| 226 | lines: vec![Line::from(Span::styled( |
| 227 | truncate_text(&title, area.width as usize), |
| 228 | Style::default().fg(theme.text).bold(), |
| 229 | ))], |
| 230 | summary: None, |
| 231 | collapsible: false, |
| 232 | }]; |
| 233 | |
| 234 | if let Some(share) = session.and_then(|s| s.share.as_ref()) { |
| 235 | sections.push(SidebarSection { |
| 236 | key: "share", |
| 237 | title: "Share", |
| 238 | lines: vec![Line::from(Span::styled( |
| 239 | truncate_text(&share.url, area.width as usize), |
| 240 | Style::default().fg(theme.info), |
| 241 | ))], |
| 242 | summary: None, |
| 243 | collapsible: false, |
| 244 | }); |
| 245 | } |
| 246 | |
| 247 | let total_cost: f64 = messages |
| 248 | .iter() |
| 249 | .filter(|m| matches!(m.role, MessageRole::Assistant)) |
| 250 | .map(|m| m.cost) |
| 251 | .sum(); |
| 252 | let total_tokens = messages |
| 253 | .iter() |