Files
ZacharyZhang-NY aac5e4ead2 T24a round 1 fix
- overlays::Dialog caps its card at the window, a title bar's height clear
  at each end, and scrolls its body while heading and actions stay; the
  fullscreen body scrolls too; test a_tall_dialog_keeps_its_actions_in_the_window
- ToolCallCard's tool name gives way with an Ellipsis, so time and chevron
  stay in a narrow column; the gallery shows one at 280px
- the Agent script shuts the card it opened, so each theme's shot opens it
- AGENTS: dialogs fit the window
2026-09-26 08:09:46 -04:00

140 lines
5.7 KiB
Rust

use std::time::Duration;
use ely_gpui_component::{
agent::{Permission, PermissionPrompt, ToolApprovalDialog, ToolCallCard, ToolCallGroup},
buttons::{Button, ButtonVariant},
chat::StepState,
theme::{ActiveTheme, TextSize},
};
use gpui::{App, IntoElement, ParentElement, SharedString, Styled, Window, div, px};
use crate::{
probe::probe,
ui::{keep, section, set},
};
const READ: &str = r#"{ "path": "src/theme/palette.rs" }"#;
const PALETTE: &str = "pub const ACCENT_LIFT: f32 = 0.18;\npub const SURFACE_LIFT: f32 = 0.04;";
const SEARCH: &str = "{\n \"query\": \"oklch lift contrast\",\n \"limit\": 5\n}";
const TESTS: &str = r#"{ "command": "cargo test --lib theme" }"#;
const WRITE: &str =
"{\n \"path\": \"src/theme/lift.rs\",\n \"content\": \"pub fn lift(color, by) -> Hsla\"\n}";
pub fn calls(_: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
section(
"ToolCallCard / ToolCallGroup",
"Each call an assistant makes: a mark for where it stands, the tool, what it touched and how long it took; a press opens its arguments and what came back. Several calls fold under one line.",
cx,
)
.child(
div()
.w(px(560.))
.flex()
.flex_col()
.gap_2()
.child(probe(
"agent-call",
div().w(px(560.)).child(
ToolCallCard::new("agent-read", "read_file", StepState::Done)
.summary("src/theme/palette.rs")
.took(Duration::from_millis(340))
.arguments(READ)
.result(PALETTE),
),
))
.child(
ToolCallCard::new("agent-search", "web_search", StepState::Working)
.summary("oklch lift contrast")
.arguments(SEARCH),
)
.child(
ToolCallCard::new("agent-tests", "run_tests", StepState::Failed)
.summary("cargo test --lib theme")
.took(Duration::from_millis(12_400))
.arguments(TESTS)
.result("2 tests failed: lift_keeps_hue, dark_lifts_further"),
)
.child(
ToolCallCard::new("agent-write", "write_file", StepState::Waiting)
.summary("src/theme/lift.rs")
.arguments(WRITE),
)
.child(
div().w(px(280.)).child(
ToolCallCard::new("agent-narrow", "mcp__filesystem__read_multiple_files", StepState::Done)
.summary("3 files")
.took(Duration::from_millis(1_100))
.arguments(READ),
),
)
.child(
ToolCallGroup::new("agent-group", "Read 3 files")
.child(ToolCallCard::new("agent-group-1", "read_file", StepState::Done).summary("src/theme/mod.rs").took(Duration::from_millis(120)))
.child(ToolCallCard::new("agent-group-2", "read_file", StepState::Done).summary("src/theme/tokens.rs").took(Duration::from_millis(95)))
.child(ToolCallCard::new("agent-group-3", "read_file", StepState::Done).summary("src/motion/curve.rs").took(Duration::from_millis(80))),
),
)
}
pub fn approval(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
let asking = keep("agent-asking", || false, window, cx);
let heard = keep("agent-heard", || None::<SharedString>, window, cx);
let allowed = keep("agent-allowed", || None::<Permission>, window, cx);
let (open, now_heard, now_allowed) =
(*asking.read(cx), heard.read(cx).clone(), *allowed.read(cx));
let (opener, closer) = (asking.clone(), asking);
let theme = cx.theme();
let note = |text: String| {
div()
.text_size(theme.text_size(TextSize::Sm))
.text_color(theme.colors.fg_muted)
.child(text)
};
section(
"ToolApprovalDialog / PermissionPrompt",
"Asking first: a dialog before one call runs, with its arguments, where Escape denies; and a prompt in place that allows once, always, or not at all.",
cx,
)
.child(
div()
.flex()
.items_center()
.gap_3()
.child(probe(
"agent-approve-open",
Button::new("agent-approve", "Review the call…")
.variant(ButtonVariant::Secondary)
.on_click(move |_, _, cx| set(&opener, true, cx)),
))
.children(now_heard.map(|text| note(text.to_string()))),
)
.child(
div()
.w(px(560.))
.flex()
.flex_col()
.gap_2()
.child(
PermissionPrompt::new("agent-permission", "Let the assistant run commands in this folder?", move |answer, _, cx| {
set(&allowed, Some(answer), cx)
})
.detail("cargo test --lib theme"),
)
.children(now_allowed.map(|answer| {
note(match answer {
Permission::Once => "Allowed once.".to_string(),
Permission::Always => "Always allowed in this folder.".to_string(),
Permission::Deny => "Denied.".to_string(),
})
})),
)
.children(open.then(|| {
ToolApprovalDialog::new("agent-approval", "write_file", WRITE, move |approved, _, cx| {
let verdict = if approved { "Ran write_file." } else { "Denied write_file." };
set(&heard, Some(verdict.into()), cx);
set(&closer, false, cx)
})
.detail("Writes a new file in src/theme.")
}))
}