terminal proof-of-concept

Richard Feldman created

Change summary

crates/acp_thread/src/acp_thread.rs | 58 +++++++++++++++++++++++-------
crates/agent2/src/agent.rs          |  2 
crates/agent_servers/src/acp.rs     |  9 ++++
3 files changed, 54 insertions(+), 15 deletions(-)

Detailed changes

crates/acp_thread/src/acp_thread.rs 🔗

@@ -1949,6 +1949,7 @@ impl AcpThread {
         extra_env: Vec<acp::EnvVariable>,
         cwd: Option<PathBuf>,
         output_byte_limit: Option<u64>,
+        is_display_only: bool,
         cx: &mut Context<Self>,
     ) -> Task<Result<Entity<Terminal>>> {
         let env = match &cwd {
@@ -1989,20 +1990,49 @@ impl AcpThread {
                 )
                 .redirect_stdin_to_dev_null()
                 .build(Some(command), &args);
-                let terminal = project
-                    .update(cx, |project, cx| {
-                        project.create_terminal_task(
-                            task::SpawnInTerminal {
-                                command: Some(command.clone()),
-                                args: args.clone(),
-                                cwd: cwd.clone(),
-                                env,
-                                ..Default::default()
-                            },
-                            cx,
-                        )
-                    })?
-                    .await?;
+
+                // For display-only terminals, create a terminal that doesn't actually execute
+                let terminal = if is_display_only {
+                    // Create a display-only terminal that just shows a header
+                    // The actual output will be streamed from the agent
+                    project
+                        .update(cx, |project, cx| {
+                            project.create_terminal_task(
+                                task::SpawnInTerminal {
+                                    // Use a simple command that shows the header and waits
+                                    // We use sleep to keep the terminal alive for output streaming
+                                    command: Some("sh".to_string()),
+                                    args: vec![
+                                        "-c".to_string(),
+                                        format!(
+                                            "echo '\\033[1;34m[Display Terminal]\\033[0m {}' && sleep 86400",
+                                            command
+                                        ),
+                                    ],
+                                    cwd: cwd.clone(),
+                                    env: Default::default(),  // Don't pass environment to avoid printing it
+                                    ..Default::default()
+                                },
+                                cx,
+                            )
+                        })?
+                        .await?
+                } else {
+                    project
+                        .update(cx, |project, cx| {
+                            project.create_terminal_task(
+                                task::SpawnInTerminal {
+                                    command: Some(command.clone()),
+                                    args: args.clone(),
+                                    cwd: cwd.clone(),
+                                    env,
+                                    ..Default::default()
+                                },
+                                cx,
+                            )
+                        })?
+                        .await?
+                };
 
                 cx.new(|cx| {
                     Terminal::new(

crates/agent2/src/agent.rs 🔗

@@ -1144,7 +1144,7 @@ impl ThreadEnvironment for AcpThreadEnvironment {
         cx: &mut AsyncApp,
     ) -> Task<Result<Rc<dyn TerminalHandle>>> {
         let task = self.acp_thread.update(cx, |thread, cx| {
-            thread.create_terminal(command, vec![], vec![], cwd, output_byte_limit, cx)
+            thread.create_terminal(command, vec![], vec![], cwd, output_byte_limit, false, cx)
         });
 
         let acp_thread = self.acp_thread.clone();

crates/agent_servers/src/acp.rs 🔗

@@ -606,6 +606,14 @@ impl acp::Client for ClientDelegate {
         &self,
         args: acp::CreateTerminalRequest,
     ) -> Result<acp::CreateTerminalResponse, acp::Error> {
+        // Check if this is a display-only terminal from the metadata
+        let is_display_only = args
+            .meta
+            .as_ref()
+            .and_then(|meta| meta.get("display_only"))
+            .and_then(|v| v.as_bool())
+            .unwrap_or(false);
+
         let terminal = self
             .session_thread(&args.session_id)?
             .update(&mut self.cx.clone(), |thread, cx| {
@@ -615,6 +623,7 @@ impl acp::Client for ClientDelegate {
                     args.env,
                     args.cwd,
                     args.output_byte_limit,
+                    is_display_only,
                     cx,
                 )
             })?