GPUI Box GitHub

Components / agent

AgentRunCanvas builder

A typed, read-mostly view of an AgentRunSnapshot on a node canvas.

A builder is RenderOnce. Construct and mount it in one expression.

use gpui_kit::agent::AgentRunCanvas;

Reviewed in agent-run-canvas.

Construct
new(ident: impl Into<Ident>, run: AgentRunSnapshot) -> Self
Options

Chain onto the value.

layout(layout: AgentRunLayout) -> Self
position(subject: RunSubjectId, x: f32, y: f32) -> Self
selected(selected: impl IntoIterator<Item = RunSubjectId>) -> Self
viewport(viewport: GraphViewport) -> Self
arrangeable(arrangeable: bool) -> Self
on_event(handler: impl Fn(&AgentRunCanvasEvent, &mut Window, &mut App) + 'static) -> Self
Reports

The variants of the event it emits. It never applies the change itself.

  • SelectionChanged
  • ViewportChanged
  • PositionChanged
Example · agent-run-canvas
fn agent_run_canvas(_window: &mut Window, cx: &mut App) -> AnyElement {
    let theme = cx.theme().clone();
    let run = AgentRunSnapshot::new("release-topology", "orchestrator")
        .execution(AgentExecutionState::Active(AgentActivity::Aggregating))
        .agents([
            AgentSnapshot::new(
                AgentDescriptor::new("orchestrator", "Atlas").role("Run coordinator"),
            )
            .execution(AgentExecutionState::Active(AgentActivity::Aggregating)),
            AgentSnapshot::new(
                AgentDescriptor::new("researcher", "Nova").role("Repository research"),
            )
            .execution(AgentExecutionState::Active(AgentActivity::UsingTool(
                "repository search".into(),
            ))),
            AgentSnapshot::new(AgentDescriptor::new("reviewer", "Sage").role("Independent review"))
                .execution(AgentExecutionState::Waiting(WaitReason::Approval)),
        ])
        .tasks([
            AgentTaskSnapshot::new("evidence", "Evidence bundle")
                .execution(AgentExecutionState::Completed(AgentOutcome::Succeeded)),
            AgentTaskSnapshot::new("synthesis", "Release synthesis").execution(
                AgentExecutionState::Completed(AgentOutcome::Partial("awaiting approval".into())),
            ),
        ])
        .links([
            RunLink::new(
                "spawn-researcher",
                RunSubjectId::Agent("orchestrator".into()),
                RunSubjectId::Agent("researcher".into()),
                RunLinkKind::Spawn,
            ),
            RunLink::new(
                "delegate-evidence",
                RunSubjectId::Agent("orchestrator".into()),
                RunSubjectId::Task("evidence".into()),
                RunLinkKind::Delegation,
            ),
            RunLink::new(
                "evidence-before-synthesis",
                RunSubjectId::Task("evidence".into()),
                RunSubjectId::Task("synthesis".into()),
                RunLinkKind::Dependency,
            ),
            RunLink::new(
                "handoff-review",
                RunSubjectId::Agent("researcher".into()),
                RunSubjectId::Agent("reviewer".into()),
                RunLinkKind::Handoff,
            ),
            RunLink::new(
                "search-report",
                RunSubjectId::Invocation("search-42".into()),
                RunSubjectId::Agent("researcher".into()),
                RunLinkKind::Report,
            ),
            RunLink::new(
                "aggregate-review",
                RunSubjectId::Agent("reviewer".into()),
                RunSubjectId::Task("synthesis".into()),
                RunLinkKind::Aggregation,
            ),
            RunLink::new(
                "retry-search",
                RunSubjectId::Agent("reviewer".into()),
                RunSubjectId::Agent("researcher".into()),
                RunLinkKind::Retry,
            )
            .label("bounded attempt 2"),
        ])
        .aggregation(AggregationSnapshot::new(3, 2).conflicts(1));

    // Laid out down the frame rather than across it, and drawn at 1:1. Four
    // node columns and the relationship wording between them are wider than
    // any frame this is reviewed in, and the zoom that made them fit put the
    // node bodies and the edge labels below the size at which they are text
    // at all: the picture said the canvas was empty and its nodes unreadable,
    // which is a claim about the component that was not true.
    stack(&theme)
        .w(px(920.0))
        .child(
            div()
                .w_full()
                .h(px(830.0))
                .surface(&theme, Surface::Panel)
                .radius(&theme, Radius::Card)
                .overflow_hidden()
                .child(
                    AgentRunCanvas::new("scene.agent-run-canvas", run)
                        .layout(AgentRunLayout::LayeredVertical)
                        .selected([RunSubjectId::Agent("researcher".into())])
                        // Panned far enough right for the retry loop, which
                        // routes around the outside of the column it returns
                        // to, to bring its own wording with it.
                        .viewport(GraphViewport::new(gpui::point(80.0, 0.0), 1.0))
                        .on_event(|_, _, _| {}),
                ),
        )
        .into_any_element()
}

Source: crates/gpui-kit/src/agent/canvas.rs