T24f Agent: control and cost

HumanInputRequest asks a question with answers to pick and a line to
write one; CostBreakdown totals a session and splits it by part.
InterruptButton, TokenUsageChart, TraceViewer and EvalResultTable
point to chat::stop_button, a stacked BarChart, TimelineProfiler and
DataTable.

UsageBar shows amounts as its owner writes them. MemoryPanel and
HumanInputRequest share agent::line::send_line; the chapter's bool
callbacks take forms::OnFlag.

DataTable scrolls columns wider than its box sideways, pinned or not,
and leaves a plain wheel to the page; sortable headers are Tab stops.
TimelineProfiler fits its ruler to its lane, its spans are Tab stops,
and a picked span takes accent.
This commit is contained in:
ZacharyZhang-NY committed 2026-09-26 11:39:24 -04:00
1 parent 96c4fe01a6
commit a29cc8bc45
20 files changed
+934 -180

No files matched your search

+28 -4
View File
@@ -1,9 +1,9 @@
use std::{collections::HashSet, rc::Rc};
use gpui::{
AnyElement, App, ElementId, Entity, InteractiveElement, IntoElement, MouseButton,
ParentElement, Pixels, Rems, SharedString, StatefulInteractiveElement, Styled, Window, div,
prelude::*,
AnyElement, App, Div, ElementId, Entity, InteractiveElement, IntoElement, MouseButton,
ParentElement, Pixels, Rems, SharedString, Stateful, StatefulInteractiveElement, Styled,
Window, div, prelude::*, transparent_black,
};
use super::{Align, Column, Row, cell::draw, model::tint, table::View};
@@ -32,6 +32,13 @@ pub(super) fn sized<E: Styled>(cell: E, column: &Column, narrowest: Rems) -> E {
}
}
/// A box a table's columns scroll sideways in; a plain wheel passes to the page.
pub(super) fn sideways(id: &ElementId) -> Stateful<Div> {
let mut sideways = div().id((id.clone(), "sideways")).overflow_x_scroll();
sideways.style().restrict_scroll_to_axis = Some(true);
sideways
}
/// What the body draws, one after another.
#[derive(Clone, Debug, PartialEq)]
pub(super) enum Line {
@@ -76,6 +83,21 @@ impl Body {
self.lead * (usize::from(self.select.is_some()) + usize::from(self.detail.is_some())) as f32
}
/// The least width columns `cols` draw in: fixed widths, the narrowest share for the rest, and the leading cells.
pub(super) fn least(&self, cols: &[usize], lead: bool, rem: Pixels) -> Pixels {
let start = match lead {
true => self.lead_width().to_pixels(rem),
false => Pixels::ZERO,
};
cols.iter().fold(start, |sum, col| {
sum + match (self.widths[*col], self.columns[*col].width) {
(Some(width), _) => width,
(None, Some(width)) => width.to_pixels(rem),
(None, None) => self.narrowest.to_pixels(rem),
}
})
}
/// Line `at` over columns `cols`; `lead` draws the leading cells.
pub(super) fn line(
&self,
@@ -266,7 +288,9 @@ impl Body {
.h_full()
.flex()
.items_center()
.px_3();
.px_3()
.border_x_1()
.border_color(transparent_black());
let frame = match self.widths[col] {
Some(width) => frame
.w(width)