@@ -9,7 +9,7 @@ use anyhow::Result;
99use schemars:: JsonSchema ;
1010use serde:: { Deserialize , Serialize } ;
1111
12- use crate :: { ContentBlock , Error , Plan , SessionId , ToolCall , ToolCallUpdate } ;
12+ use crate :: { ContentBlock , EnvVariable , Error , Plan , SessionId , ToolCall , ToolCallUpdate } ;
1313
1414/// Defines the interface that ACP-compliant clients must implement.
1515///
@@ -54,6 +54,16 @@ pub trait Client {
5454 args : ReadTextFileRequest ,
5555 ) -> impl Future < Output = Result < ReadTextFileResponse , Error > > ;
5656
57+ fn new_terminal (
58+ & self ,
59+ args : NewTerminalRequest ,
60+ ) -> impl Future < Output = Result < NewTerminalResponse , Error > > ;
61+
62+ fn terminal_output (
63+ & self ,
64+ args : TerminalOutputRequest ,
65+ ) -> impl Future < Output = Result < TerminalOutputResponse , Error > > ;
66+
5767 /// Handles session update notifications from the agent.
5868 ///
5969 /// This is a notification endpoint (no response expected) that receives
@@ -244,6 +254,60 @@ pub struct ReadTextFileResponse {
244254 pub content : String ,
245255}
246256
257+ // Terminals
258+
259+ #[ derive( Debug , Clone , Serialize , Deserialize , JsonSchema , PartialEq , Eq , Hash ) ]
260+ #[ serde( transparent) ]
261+ pub struct TerminalId ( pub Arc < str > ) ;
262+
263+ impl std:: fmt:: Display for TerminalId {
264+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
265+ write ! ( f, "{}" , self . 0 )
266+ }
267+ }
268+
269+ #[ derive( Debug , Clone , Serialize , Deserialize , JsonSchema ) ]
270+ #[ schemars( extend( "x-side" = "client" , "x-method" = "terminal/new" ) ) ]
271+ #[ serde( rename_all = "camelCase" ) ]
272+ pub struct NewTerminalRequest {
273+ pub session_id : SessionId ,
274+ pub command : String ,
275+ #[ serde( default , skip_serializing_if = "Vec::is_empty" ) ]
276+ pub args : Vec < String > ,
277+ #[ serde( default , skip_serializing_if = "Vec::is_empty" ) ]
278+ pub env : Vec < EnvVariable > ,
279+ #[ serde( default , skip_serializing_if = "Option::is_none" ) ]
280+ pub cwd : Option < PathBuf > ,
281+ #[ serde( default , skip_serializing_if = "Option::is_none" ) ]
282+ pub output_byte_limit : Option < u64 > ,
283+ }
284+
285+ #[ derive( Debug , Clone , Serialize , Deserialize , JsonSchema ) ]
286+ #[ schemars( extend( "x-side" = "client" , "x-method" = "terminal/new" ) ) ]
287+ #[ serde( rename_all = "camelCase" ) ]
288+ pub struct NewTerminalResponse {
289+ pub terminal_id : TerminalId ,
290+ }
291+
292+ #[ derive( Debug , Clone , Serialize , Deserialize , JsonSchema ) ]
293+ #[ schemars( extend( "x-side" = "client" , "x-method" = "terminal/output" ) ) ]
294+ #[ serde( rename_all = "camelCase" ) ]
295+ pub struct TerminalOutputRequest {
296+ pub session_id : SessionId ,
297+ pub terminal_id : TerminalId ,
298+ }
299+
300+ #[ derive( Debug , Clone , Serialize , Deserialize , JsonSchema ) ]
301+ #[ schemars( extend( "x-side" = "client" , "x-method" = "terminal/output" ) ) ]
302+ #[ serde( rename_all = "camelCase" ) ]
303+ pub struct TerminalOutputResponse {
304+ pub output : String ,
305+ pub truncated : bool ,
306+ pub finished : bool ,
307+ pub exit_code : Option < u32 > ,
308+ pub signal : Option < String > ,
309+ }
310+
247311// Capabilities
248312
249313/// Capabilities supported by the client.
@@ -259,6 +323,8 @@ pub struct ClientCapabilities {
259323 /// Determines which file operations the agent can request.
260324 #[ serde( default ) ]
261325 pub fs : FileSystemCapability ,
326+ #[ serde( default ) ]
327+ pub terminal : bool ,
262328}
263329
264330/// File system capabilities that a client may support.
@@ -290,6 +356,10 @@ pub struct ClientMethodNames {
290356 pub fs_write_text_file : & ' static str ,
291357 /// Method for reading text files.
292358 pub fs_read_text_file : & ' static str ,
359+ /// Method for creating new terminals.
360+ pub terminal_new : & ' static str ,
361+ /// Method for getting terminals output.
362+ pub terminal_output : & ' static str ,
293363}
294364
295365/// Constant containing all client method names.
@@ -298,6 +368,8 @@ pub const CLIENT_METHOD_NAMES: ClientMethodNames = ClientMethodNames {
298368 session_request_permission : SESSION_REQUEST_PERMISSION_METHOD_NAME ,
299369 fs_write_text_file : FS_WRITE_TEXT_FILE_METHOD_NAME ,
300370 fs_read_text_file : FS_READ_TEXT_FILE_METHOD_NAME ,
371+ terminal_new : TERMINAL_NEW_METHOD_NAME ,
372+ terminal_output : TERMINAL_OUTPUT_METHOD_NAME ,
301373} ;
302374
303375/// Notification name for session updates.
@@ -308,6 +380,10 @@ pub(crate) const SESSION_REQUEST_PERMISSION_METHOD_NAME: &str = "session/request
308380pub ( crate ) const FS_WRITE_TEXT_FILE_METHOD_NAME : & str = "fs/write_text_file" ;
309381/// Method name for reading text files.
310382pub ( crate ) const FS_READ_TEXT_FILE_METHOD_NAME : & str = "fs/read_text_file" ;
383+ /// Method name for creating a new terminal.
384+ pub ( crate ) const TERMINAL_NEW_METHOD_NAME : & str = "terminal/new" ;
385+ /// Method for getting terminals output.
386+ pub ( crate ) const TERMINAL_OUTPUT_METHOD_NAME : & str = "terminal/output" ;
311387
312388/// All possible requests that an agent can send to a client.
313389///
@@ -322,6 +398,8 @@ pub enum AgentRequest {
322398 WriteTextFileRequest ( WriteTextFileRequest ) ,
323399 ReadTextFileRequest ( ReadTextFileRequest ) ,
324400 RequestPermissionRequest ( RequestPermissionRequest ) ,
401+ NewTerminalRequest ( NewTerminalRequest ) ,
402+ TerminalOutputRequest ( TerminalOutputRequest ) ,
325403}
326404
327405/// All possible responses that a client can send to an agent.
@@ -337,6 +415,8 @@ pub enum ClientResponse {
337415 WriteTextFileResponse ,
338416 ReadTextFileResponse ( ReadTextFileResponse ) ,
339417 RequestPermissionResponse ( RequestPermissionResponse ) ,
418+ NewTerminalResponse ( NewTerminalResponse ) ,
419+ TerminalOutputResponse ( TerminalOutputResponse ) ,
340420}
341421
342422/// All possible notifications that an agent can send to a client.
0 commit comments