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:
1 parent
061be8a0ff
commit
37e53a5ecb
20 files changed
+934
-180
No files matched your search
@@ -1,4 +1,7 @@
|
||||
use std::f32::consts::{FRAC_PI_4, TAU};
|
||||
use std::{
|
||||
f32::consts::{FRAC_PI_4, TAU},
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
use gpui::{
|
||||
Animation, AnimationExt, App, ElementId, FontWeight, Hsla, IntoElement, ParentElement,
|
||||
@@ -282,11 +285,14 @@ impl RenderOnce for Gauge {
|
||||
}
|
||||
}
|
||||
|
||||
/// How a whole divides: one bar of colored parts with the free rest as track, and a legend of each part's share.
|
||||
type Amounts = Rc<dyn Fn(f64) -> String>;
|
||||
|
||||
/// How a whole divides: one bar of colored parts with the free rest as track, and a legend of each part's share or amount.
|
||||
#[derive(IntoElement)]
|
||||
pub struct UsageBar {
|
||||
total: f64,
|
||||
parts: Vec<(SharedString, f64)>,
|
||||
amounts: Option<Amounts>,
|
||||
}
|
||||
|
||||
impl UsageBar {
|
||||
@@ -299,9 +305,16 @@ impl UsageBar {
|
||||
Self {
|
||||
total,
|
||||
parts: Vec::new(),
|
||||
amounts: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Shows each part's amount, as `write` puts it, in place of its share.
|
||||
pub fn amounts(mut self, write: impl Fn(f64) -> String + 'static) -> Self {
|
||||
self.amounts = Some(Rc::new(write));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn part(mut self, name: impl Into<SharedString>, amount: f64) -> Self {
|
||||
assert!(amount >= 0.0, "a part cannot be negative, got {amount}");
|
||||
self.parts.push((name.into(), amount));
|
||||
@@ -320,6 +333,14 @@ impl UsageBar {
|
||||
);
|
||||
(used, used >= self.total * (1.0 - 1e-9))
|
||||
}
|
||||
|
||||
/// A part's figure in the legend: its amount as `amounts` writes it, or its share.
|
||||
fn figure(&self, amount: f64) -> String {
|
||||
match &self.amounts {
|
||||
Some(write) => write(amount),
|
||||
None => format::percent(amount / self.total, 0, false),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for UsageBar {
|
||||
@@ -372,7 +393,7 @@ impl RenderOnce for UsageBar {
|
||||
.child(
|
||||
tabular(div())
|
||||
.text_color(colors.fg_muted)
|
||||
.child(format::percent(amount / total, 0, false)),
|
||||
.child(self.figure(*amount)),
|
||||
)
|
||||
});
|
||||
div().flex().flex_col().gap_2().child(bar).child(
|
||||
@@ -398,6 +419,14 @@ mod tests {
|
||||
assert!(!UsageBar::new(1.0).part("a", 0.5).used().1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_part_reads_as_its_share_or_as_written() {
|
||||
let bar = UsageBar::new(4.0).part("a", 1.0);
|
||||
assert_eq!(bar.figure(1.0), "25%");
|
||||
let bar = bar.amounts(|amount| format!("{amount} GB"));
|
||||
assert_eq!(bar.figure(1.0), "1 GB");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_share_turns_amber_then_red() {
|
||||
let limits = (0.8, 0.95);
|
||||
|
||||
Reference in new issue
Block a user