T24d: Agent, previews
- BrowserPreview: the address with a lock and a spinner while it loads, the host's frame shown, and the frames so far along the foot as Tab stops; ScreenshotStream is that strip - ComputerUseViewer: the host's frame, a ring where the agent points that rings again at each new point, and what it does there - LivePreview: the host's page under its address, with reload - ArtifactPanel: title, versions through chat::BranchNavigator, Preview and Source when it has both, copy and download; it fails loud with neither - gallery: frames cut from the gallery's own pages; one asset! macro in main.rs replaces three copies
This commit is contained in:
1 parent
8c92651e6a
commit
dcc4a39e56
16 files changed
+842
-36
No files matched your search
Binary file not shown.
|
After Width: | Height: | Size: 63 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 94 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 77 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 60 KiB |
@@ -1,3 +1,14 @@
|
||||
/// A file under the gallery's assets, by name.
|
||||
macro_rules! asset {
|
||||
($name:literal) => {
|
||||
concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/examples/gallery/assets/",
|
||||
$name
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
mod capture;
|
||||
mod pages;
|
||||
mod probe;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
mod changes;
|
||||
mod previews;
|
||||
mod progress;
|
||||
mod tools;
|
||||
|
||||
@@ -11,7 +12,7 @@ pub const PAGE: Page = Page {
|
||||
number: 24,
|
||||
slug: "agent",
|
||||
title: "Agent",
|
||||
summary: "An assistant at work: the tools it calls, what it asks before it acts, how far it has come and what it would change.",
|
||||
summary: "An assistant at work: the tools it calls, what it asks before it acts, how far it has come, what it would change, what it sees and what it makes.",
|
||||
render,
|
||||
script: SCRIPT,
|
||||
};
|
||||
@@ -39,6 +40,9 @@ const SCRIPT: &[Step] = &[
|
||||
Step::DownAt("agent-changes", 30.0, 51.0),
|
||||
Step::UpAt("agent-changes", 30.0, 51.0),
|
||||
Step::Wait(200),
|
||||
Step::Click("agent-pointer-next"),
|
||||
Step::Wait(400),
|
||||
Step::Shot("pointer"),
|
||||
];
|
||||
|
||||
fn render(window: &mut Window, cx: &mut App) -> AnyElement {
|
||||
@@ -48,5 +52,7 @@ fn render(window: &mut Window, cx: &mut App) -> AnyElement {
|
||||
.child(progress::steps(window, cx))
|
||||
.child(progress::agents(window, cx))
|
||||
.child(changes::changes_section(window, cx))
|
||||
.child(previews::watching(window, cx))
|
||||
.child(previews::artifacts(window, cx))
|
||||
.into_any_element()
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
use ely_gpui_component::{
|
||||
agent::{ArtifactPanel, BrowserPreview, ComputerUseViewer, LivePreview},
|
||||
buttons::{Button, ButtonVariant},
|
||||
chat::CodeBlock,
|
||||
documents::MarkdownRenderer,
|
||||
primitives::IconName,
|
||||
theme::{ActiveTheme, TextSize},
|
||||
typography::format::plural,
|
||||
};
|
||||
use gpui::{
|
||||
App, ClipboardItem, FontWeight, IntoElement, ParentElement, Styled, Window, div, point, px,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
probe::probe,
|
||||
ui::{keep, section, set},
|
||||
};
|
||||
|
||||
const FRAMES: [&str; 3] = [
|
||||
asset!("frames/frame-1.jpg"),
|
||||
asset!("frames/frame-2.jpg"),
|
||||
asset!("frames/frame-3.jpg"),
|
||||
];
|
||||
|
||||
const ADDRESSES: [&str; 3] = [
|
||||
"localhost:5173/navigation",
|
||||
"localhost:5173/git",
|
||||
"localhost:5173/chat",
|
||||
];
|
||||
|
||||
/// Where the agent points on the screen, and what it does there.
|
||||
const ACTIONS: [(f32, f32, &str); 3] = [
|
||||
(0.42, 0.31, "Click Full name"),
|
||||
(0.42, 0.31, "Type Ada Lovelace"),
|
||||
(0.34, 0.82, "Click Password"),
|
||||
];
|
||||
|
||||
pub fn watching(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
||||
let shown = keep("agent-frame", || 2_usize, window, cx);
|
||||
let step = keep("agent-pointer", || 0_usize, window, cx);
|
||||
let (now, at) = (*shown.read(cx), *step.read(cx));
|
||||
let (x, y, action) = ACTIONS[at];
|
||||
section(
|
||||
"BrowserPreview / ScreenshotStream / ComputerUseViewer",
|
||||
"What an agent sees as it works, in frames from the host: a browser with its address and the frames so far, a press on one shows it; and a screen with where the agent points, a ring for each new point, and what it does there.",
|
||||
cx,
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.items_start()
|
||||
.gap_6()
|
||||
.child(
|
||||
div().w(px(480.)).child(
|
||||
BrowserPreview::new("agent-browser", ADDRESSES[now], FRAMES, now)
|
||||
.loading(now == FRAMES.len() - 1)
|
||||
.on_show(move |ix, _, cx| set(&shown, ix, cx)),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.w(px(420.))
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_3()
|
||||
.child(
|
||||
ComputerUseViewer::new("agent-screen", asset!("frames/screen.jpg"))
|
||||
.pointer(point(x, y))
|
||||
.action(action),
|
||||
)
|
||||
.child(probe(
|
||||
"agent-pointer-next",
|
||||
Button::new("agent-pointer-next", "Next action")
|
||||
.variant(ButtonVariant::Secondary)
|
||||
.on_click(move |_, _, cx| {
|
||||
let next = (*step.read(cx) + 1) % ACTIONS.len();
|
||||
set(&step, next, cx)
|
||||
}),
|
||||
)),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
const NOTE: &str = "# Lift\n\nA **lift** blends a color toward white. Dark themes lift their accents further, because saturated color on charcoal looks louder.\n\n- Accents lift by 18%\n- Surfaces lift by 4%";
|
||||
|
||||
const LIFT: &str =
|
||||
"pub fn lift(color: Hsla, by: f32) -> Hsla {\n color.mix(white(), by.clamp(0.0, 1.0))\n}";
|
||||
|
||||
/// A small page as the host would draw it.
|
||||
fn page(builds: usize, cx: &App) -> impl IntoElement + use<> {
|
||||
let theme = cx.theme();
|
||||
div()
|
||||
.p_6()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_3()
|
||||
.child(
|
||||
div()
|
||||
.text_size(theme.text_size(TextSize::Xl))
|
||||
.font_weight(FontWeight::SEMIBOLD)
|
||||
.child("Lift"),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.text_color(theme.colors.fg_muted)
|
||||
.child("Blend a color toward white."),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.child(Button::new("agent-page-try", "Try it").variant(ButtonVariant::Primary)),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.text_size(theme.text_size(TextSize::Xs))
|
||||
.text_color(theme.colors.fg_subtle)
|
||||
.child(format!("Built {}", plural(builds as u64, "time", "times"))),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn artifacts(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
||||
let version = keep("agent-version", || 2_usize, window, cx);
|
||||
let builds = keep("agent-builds", || 1_usize, window, cx);
|
||||
let (now, built) = (*version.read(cx), *builds.read(cx));
|
||||
section(
|
||||
"ArtifactPanel / ArtifactVersionSwitcher / LivePreview",
|
||||
"What an agent made, in a panel of its own: the version shown among all, copy and download, the artifact as preview or source; the version switcher is chat::BranchNavigator. A live preview holds the host's page with its address and reload.",
|
||||
cx,
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.items_start()
|
||||
.gap_6()
|
||||
.child(
|
||||
div().w(px(460.)).h(px(360.)).child(
|
||||
ArtifactPanel::new("agent-note", "Notes on lift", IconName::FileText)
|
||||
.version(now, 3, move |to, _, cx| set(&version, to, cx))
|
||||
.preview(div().p_4().child(MarkdownRenderer::new("agent-note-text", NOTE)))
|
||||
.source(div().p_3().child(CodeBlock::new("agent-note-source", NOTE).language("markdown")))
|
||||
.on_copy(|_, cx| cx.write_to_clipboard(ClipboardItem::new_string(NOTE.to_string()))),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div().w(px(420.)).h(px(360.)).child(
|
||||
ArtifactPanel::new("agent-code", "lift.rs", IconName::Code)
|
||||
.source(div().p_3().child(CodeBlock::new("agent-code-source", LIFT).language("rust"))),
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.w(px(460.))
|
||||
.h(px(280.))
|
||||
.child(
|
||||
LivePreview::new("agent-live", "localhost:5173/lift", page(built, cx))
|
||||
.on_reload(move |_, cx| {
|
||||
let next = *builds.read(cx) + 1;
|
||||
set(&builds, next, cx)
|
||||
}),
|
||||
),
|
||||
)
|
||||
}
|
||||
@@ -11,16 +11,6 @@ use gpui::{App, IntoElement, ParentElement, Styled, Window, div, px};
|
||||
|
||||
use crate::ui::{keep, noise, section, set};
|
||||
|
||||
macro_rules! asset {
|
||||
($name:literal) => {
|
||||
concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/examples/gallery/assets/",
|
||||
$name
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
const SHORT: &str = "fn lift(c: f32, t: f32) -> f32 {\n c + t * (1.0 - c)\n}";
|
||||
|
||||
const LONG: &str = "/// Every accent in the library, lifted for its theme.\npub struct Accents {\n base: Hsla,\n light: f32,\n dark: f32,\n}\n\nimpl Accents {\n pub fn new(base: Hsla) -> Self {\n Self { base, light: 0.5, dark: 0.62 }\n }\n\n /// The accent as the theme shows it.\n pub fn shown(&self, dark: bool) -> Hsla {\n let t = if dark { self.dark } else { self.light };\n lift(self.base, t)\n }\n\n /// A hover, one step louder.\n pub fn hover(&self, dark: bool) -> Hsla {\n lift(self.shown(dark), 0.08)\n }\n\n /// A press, two steps louder.\n pub fn press(&self, dark: bool) -> Hsla {\n lift(self.shown(dark), 0.16)\n }\n}";
|
||||
|
||||
@@ -19,16 +19,6 @@ use crate::{
|
||||
ui::{keep, noise, section, set},
|
||||
};
|
||||
|
||||
macro_rules! asset {
|
||||
($name:literal) => {
|
||||
concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/examples/gallery/assets/",
|
||||
$name
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
const SYSTEM: &str = "You answer about color in plain words. Cite sources.";
|
||||
|
||||
/// The composer's text, which the prompt menu fills.
|
||||
|
||||
@@ -15,16 +15,6 @@ use crate::{
|
||||
ui::{keep, section, set},
|
||||
};
|
||||
|
||||
macro_rules! asset {
|
||||
($name:literal) => {
|
||||
concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/examples/gallery/assets/",
|
||||
$name
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
const PICTURES: [(&str, &str); 6] = [
|
||||
(asset!("dunes-sun.jpg"), "Sunset over the dunes"),
|
||||
(asset!("atrium-stair.jpg"), "A stair that turns"),
|
||||
|
||||
Reference in new issue
Block a user