use ai_app::client::QuestionOption; use ai_app::client::transcript_fold::{QuestionCard, TranscriptItem, TranscriptRow as FoldedRow}; use iris::prelude::*; fn main() { DesktopApp::::run(); } #[derive(DesktopUiState)] pub struct Client { ui_state: DesktopUiState, #[allow(dead_code)] screen: ai_app::ui::TranscriptScreen, } fn msg(seq: u64, from_user: bool, text: &str) -> FoldedRow { FoldedRow::Single(if from_user { TranscriptItem::UserMsg { seq, text: text.to_string(), attachments: Vec::new(), } } else { TranscriptItem::AssistantMsg { seq, text: text.to_string(), settled: true, } }) } fn tool_call(id: &str, tool: &str, input: &str, result: Option<(&str, bool)>) -> TranscriptItem { tool_call_in("run1", id, tool, input, result) } fn tool_call_in( run: &str, id: &str, tool: &str, input: &str, result: Option<(&str, bool)>, ) -> TranscriptItem { TranscriptItem::ToolRun { seq: 3, id: id.into(), run_id: run.into(), tool: tool.into(), input: input.into(), output: result.map(|(out, _)| out.to_string()).unwrap_or_default(), done: result.is_some(), failed: result.is_some_and(|(_, failed)| failed), asks: Vec::new(), images: Vec::new(), } } fn asking(id: &str, tool: &str, input: &str) -> TranscriptItem { let mut call = tool_call_in("run2", id, tool, input, None); if let TranscriptItem::ToolRun { asks, .. } = &mut call { asks.push(QuestionCard { seq: 9, id: format!("{id}-q"), prompt: "Allow this command?".into(), header: None, options: vec![ QuestionOption { label: "Allow".into(), description: None, preview: None, }, QuestionOption { label: "Deny".into(), description: None, preview: None, }, ], multi_select: false, answers: Vec::new(), }); } call } fn long_output() -> String { (0..200) .map(|i| format!("test ai_app::ui::case_{i} ... ok")) .collect::>() .join("\n") } fn synthetic_rows() -> Vec { vec![ msg( 1, true, "Can you show me a **bold** word, some *italic* text, and `inline code`?", ), msg( 2, false, "# Sure\n\nHere's a [link to the repo](https://example.com/ai-app-2) and a fenced block:\n\n```rust\nfn main() {\n println!(\"hi\");\n}\n```", ), FoldedRow::Tools(vec![ tool_call( "t1", "Read", r#"{"file_path": "src/main.rs"}"#, Some(("fn main() {}\n", false)), ), tool_call( "t2", "Bash", r#"{"command": "cargo build --release", "timeout": 480000, "description": "Build it"}"#, Some(( "error: could not compile `iris`\nCaused by: linker not found", true, )), ), tool_call("t3", "Grep", r#"{"pattern": "fn fold_event"}"#, None), ]), FoldedRow::Single(tool_call( "t5", "Bash", r#"{"command": "cargo test -p transcript-ui -- --nocapture"}"#, Some((&long_output(), false)), )), msg(6, true, "Looks good, thanks!"), msg(7, false, BLOCK_SAMPLER), ] } const BLOCK_SAMPLER: &str = "\ ## What changed Iris **fold** render measure session window anchor context transcript \ iris measure iris scroll call transcript layout *cursor* context, and a \ [bench](https://example.com/bench) link. ```rust fn fold_event(items: Vec, seq: u64) -> Vec { let mut out = items; out.push(Item::new(seq)); out } ``` | column | value | |---|---| | a | measure place draw tool call token context window anchor | - one bullet - another, with `inline code` - nested one level 1. first numbered 2. second numbered > A quoted line, to show the bar and the indent. "; impl DesktopAppState for Client { fn new( mut ui_state: DesktopUiState, rsc: &mut DesktopRsc, _: Proxy, ) -> Self { let mut screen = ai_app::ui::build(rsc, &mut ui_state, synthetic_rows()); screen.push_row( rsc, &FoldedRow::Single(TranscriptItem::CommandRow { seq: 8, text: "clear".into(), }), ); screen.push_row( rsc, &FoldedRow::Tools(vec![ tool_call_in( "run2", "t6", "Read", r#"{"file_path": "docs/RUST.md"}"#, Some(("# Moving the app to Rust\n", false)), ), tool_call_in( "run2", "t7", "Bash", r#"{"command": "cargo clippy --workspace --all-targets"}"#, Some(("error: unused variable `x`", true)), ), tool_call_in("run2", "t8", "Glob", r#"{"pattern": "**/*.rs"}"#, None), asking( "t9", "Bash", r#"{"command": "rm -rf target", "timeout": 120000, "description": "Clear the build"}"#, ), ]), ); screen.set_session_working(rsc, true); if std::env::var_os("IRIS_TOOLS_EXPANDED").is_some() { assert!( screen.expand_tail_tools(rsc, true), "the newest row must be the tool run this flag is about" ); } Self { ui_state, screen } } }