44
55package com .agentclientprotocol .sdk .agent ;
66
7+ import java .util .ArrayList ;
8+ import java .util .List ;
9+ import java .util .UUID ;
10+
711import com .agentclientprotocol .sdk .capabilities .NegotiatedCapabilities ;
812import com .agentclientprotocol .sdk .spec .AcpSchema ;
13+ import com .agentclientprotocol .sdk .spec .AcpSchema .AgentMessageChunk ;
14+ import com .agentclientprotocol .sdk .spec .AcpSchema .AgentThoughtChunk ;
15+ import com .agentclientprotocol .sdk .spec .AcpSchema .CreateTerminalRequest ;
16+ import com .agentclientprotocol .sdk .spec .AcpSchema .EnvVariable ;
17+ import com .agentclientprotocol .sdk .spec .AcpSchema .PermissionOption ;
18+ import com .agentclientprotocol .sdk .spec .AcpSchema .PermissionOptionKind ;
19+ import com .agentclientprotocol .sdk .spec .AcpSchema .PermissionSelected ;
20+ import com .agentclientprotocol .sdk .spec .AcpSchema .ReadTextFileRequest ;
21+ import com .agentclientprotocol .sdk .spec .AcpSchema .ReleaseTerminalRequest ;
22+ import com .agentclientprotocol .sdk .spec .AcpSchema .RequestPermissionRequest ;
23+ import com .agentclientprotocol .sdk .spec .AcpSchema .TerminalOutputRequest ;
24+ import com .agentclientprotocol .sdk .spec .AcpSchema .TextContent ;
25+ import com .agentclientprotocol .sdk .spec .AcpSchema .ToolCallStatus ;
26+ import com .agentclientprotocol .sdk .spec .AcpSchema .ToolCallUpdate ;
27+ import com .agentclientprotocol .sdk .spec .AcpSchema .ToolKind ;
28+ import com .agentclientprotocol .sdk .spec .AcpSchema .WaitForTerminalExitRequest ;
29+ import com .agentclientprotocol .sdk .spec .AcpSchema .WriteTextFileRequest ;
930import reactor .core .publisher .Mono ;
1031
1132/**
@@ -23,14 +44,22 @@ class DefaultPromptContext implements PromptContext {
2344
2445 private final AcpAsyncAgent agent ;
2546
47+ private final String sessionId ;
48+
2649 /**
2750 * Creates a new prompt context wrapping the given agent.
2851 * @param agent The agent to delegate to
52+ * @param sessionId The session ID for this prompt invocation
2953 */
30- DefaultPromptContext (AcpAsyncAgent agent ) {
54+ DefaultPromptContext (AcpAsyncAgent agent , String sessionId ) {
3155 this .agent = agent ;
56+ this .sessionId = sessionId ;
3257 }
3358
59+ // ========================================================================
60+ // Low-Level API
61+ // ========================================================================
62+
3463 @ Override
3564 public Mono <Void > sendUpdate (String sessionId , AcpSchema .SessionUpdate update ) {
3665 return agent .sendSessionUpdate (sessionId , update );
@@ -82,4 +111,109 @@ public NegotiatedCapabilities getClientCapabilities() {
82111 return agent .getClientCapabilities ();
83112 }
84113
114+ // ========================================================================
115+ // Convenience API
116+ // ========================================================================
117+
118+ @ Override
119+ public String getSessionId () {
120+ return sessionId ;
121+ }
122+
123+ @ Override
124+ public Mono <Void > sendMessage (String text ) {
125+ return sendUpdate (sessionId , new AgentMessageChunk ("agent_message_chunk" , new TextContent (text )));
126+ }
127+
128+ @ Override
129+ public Mono <Void > sendThought (String text ) {
130+ return sendUpdate (sessionId , new AgentThoughtChunk ("agent_thought_chunk" , new TextContent (text )));
131+ }
132+
133+ @ Override
134+ public Mono <String > readFile (String path ) {
135+ return readFile (path , null , null );
136+ }
137+
138+ @ Override
139+ public Mono <String > readFile (String path , Integer startLine , Integer lineCount ) {
140+ return readTextFile (new ReadTextFileRequest (sessionId , path , startLine , lineCount ))
141+ .map (AcpSchema .ReadTextFileResponse ::content );
142+ }
143+
144+ @ Override
145+ public Mono <Void > writeFile (String path , String content ) {
146+ return writeTextFile (new WriteTextFileRequest (sessionId , path , content )).then ();
147+ }
148+
149+ @ Override
150+ public Mono <Boolean > askPermission (String action ) {
151+ ToolCallUpdate toolCall = new ToolCallUpdate (
152+ UUID .randomUUID ().toString (), action , ToolKind .EDIT , ToolCallStatus .PENDING ,
153+ null , null , null , null );
154+
155+ List <PermissionOption > options = List .of (
156+ new PermissionOption ("allow" , "Allow" , PermissionOptionKind .ALLOW_ONCE ),
157+ new PermissionOption ("deny" , "Deny" , PermissionOptionKind .REJECT_ONCE ));
158+
159+ return requestPermission (new RequestPermissionRequest (sessionId , toolCall , options ))
160+ .map (response -> response .outcome () instanceof PermissionSelected s
161+ && "allow" .equals (s .optionId ()));
162+ }
163+
164+ @ Override
165+ public Mono <String > askChoice (String question , String ... options ) {
166+ if (options == null || options .length < 2 ) {
167+ return Mono .error (new IllegalArgumentException ("At least 2 options are required" ));
168+ }
169+
170+ List <PermissionOption > permOptions = new ArrayList <>();
171+ for (int i = 0 ; i < options .length ; i ++) {
172+ permOptions .add (new PermissionOption (
173+ String .valueOf (i ), options [i ], PermissionOptionKind .ALLOW_ONCE ));
174+ }
175+
176+ ToolCallUpdate toolCall = new ToolCallUpdate (
177+ UUID .randomUUID ().toString (), question , ToolKind .OTHER ,
178+ ToolCallStatus .PENDING , null , null , null , null );
179+
180+ return requestPermission (new RequestPermissionRequest (sessionId , toolCall , permOptions ))
181+ .map (response -> {
182+ if (response .outcome () instanceof PermissionSelected s ) {
183+ int idx = Integer .parseInt (s .optionId ());
184+ return options [idx ];
185+ }
186+ return null ;
187+ });
188+ }
189+
190+ @ Override
191+ public Mono <CommandResult > execute (String ... commandAndArgs ) {
192+ return execute (Command .of (commandAndArgs ));
193+ }
194+
195+ @ Override
196+ public Mono <CommandResult > execute (Command command ) {
197+ // Convert env map to list of EnvVariable
198+ List <EnvVariable > envList = null ;
199+ if (command .env () != null ) {
200+ envList = command .env ().entrySet ().stream ()
201+ .map (e -> new EnvVariable (e .getKey (), e .getValue ()))
202+ .toList ();
203+ }
204+
205+ return createTerminal (new CreateTerminalRequest (
206+ sessionId , command .executable (), command .args (),
207+ command .cwd (), envList , command .outputByteLimit ()))
208+ .flatMap (createResp -> {
209+ String terminalId = createResp .terminalId ();
210+
211+ return waitForTerminalExit (new WaitForTerminalExitRequest (sessionId , terminalId ))
212+ .flatMap (exitResp -> getTerminalOutput (new TerminalOutputRequest (sessionId , terminalId ))
213+ .map (outputResp -> new CommandResult (outputResp .output (), exitResp .exitCode (), false )))
214+ .doFinally (signal -> releaseTerminal (new ReleaseTerminalRequest (sessionId , terminalId ))
215+ .subscribe ());
216+ });
217+ }
218+
85219}
0 commit comments