Skip to content

Commit 20d99fb

Browse files
committed
Update interfaces
1 parent 4f85465 commit 20d99fb

5 files changed

Lines changed: 276 additions & 49 deletions

File tree

Lines changed: 68 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
package io.agentclientprotocol.agent
22

33
import io.agentclientprotocol.model.AuthenticateRequest
4+
import io.agentclientprotocol.model.AuthenticateResponse
45
import io.agentclientprotocol.model.CancelNotification
56
import io.agentclientprotocol.model.InitializeRequest
67
import io.agentclientprotocol.model.InitializeResponse
78
import io.agentclientprotocol.model.LoadSessionRequest
9+
import io.agentclientprotocol.model.LoadSessionResponse
810
import io.agentclientprotocol.model.NewSessionRequest
911
import io.agentclientprotocol.model.NewSessionResponse
1012
import io.agentclientprotocol.model.PromptRequest
1113
import io.agentclientprotocol.model.PromptResponse
14+
import io.agentclientprotocol.model.SetSessionModeRequest
15+
import io.agentclientprotocol.model.SetSessionModeResponse
1216

1317
/**
1418
* Interface that agents must implement to handle client requests.
@@ -33,54 +37,98 @@ public interface Agent {
3337
/**
3438
* Authenticate using the specified authentication method.
3539
*
36-
* Called when the client wants to authenticate with a specific method
37-
* that was advertised in the initialize response.
40+
* Called when the agent requires authentication before allowing session creation.
41+
* The client provides the authentication method ID that was advertised during initialization.
42+
* After successful authentication, the client can proceed to create sessions without
43+
* receiving an `auth_required` error.
44+
*
45+
* See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)
3846
*
3947
* @param request The authentication request containing the method ID
40-
* @return null (authentication is just a handshake)
48+
* @return Authentication response
4149
*/
42-
public suspend fun authenticate(request: AuthenticateRequest)
50+
public suspend fun authenticate(request: AuthenticateRequest): AuthenticateResponse
4351

4452
/**
4553
* Create a new conversation session.
4654
*
47-
* Sessions maintain their own context and allow multiple independent
48-
* conversations with the same agent.
55+
* Sessions represent independent conversation contexts with their own history and state.
56+
* The agent should create a new session context, connect to any specified MCP servers,
57+
* and return a unique session ID for future requests.
58+
*
59+
* May return an `auth_required` error if the agent requires authentication.
4960
*
5061
* See protocol docs: [Creating a Session](https://agentclientprotocol.com/protocol/session-setup#creating-a-session)
62+
*
63+
* @param request The session creation request with working directory and MCP servers
64+
* @return The session ID and optional mode/model state
5165
*/
52-
public suspend fun newSession(request: NewSessionRequest): NewSessionResponse
66+
public suspend fun sessionNew(request: NewSessionRequest): NewSessionResponse
5367

5468
/**
55-
* Load an existing conversation session.
69+
* Load an existing conversation session to resume a previous conversation.
5670
*
5771
* Only called if the agent advertises the `loadSession` capability.
58-
* Allows resuming previous conversations.
72+
* The agent should restore the session context and conversation history, connect to
73+
* the specified MCP servers, and stream the entire conversation history back to the
74+
* client via notifications.
5975
*
6076
* See protocol docs: [Loading Sessions](https://agentclientprotocol.com/protocol/session-setup#loading-sessions)
77+
*
78+
* @param request The session load request with session ID, working directory, and MCP servers
79+
* @return Optional mode/model state for the loaded session
80+
*/
81+
public suspend fun sessionLoad(request: LoadSessionRequest): LoadSessionResponse
82+
83+
/**
84+
* Sets the operational mode for a session.
85+
*
86+
* Allows switching between different agent modes (e.g., "ask", "architect", "code")
87+
* that affect system prompts, tool availability, and permission behaviors. The mode
88+
* must be one of the modes advertised in `availableModes` during session creation or loading.
89+
*
90+
* This method can be called at any time during a session, whether the agent is idle or
91+
* actively generating a turn. Agents may also change modes autonomously and notify the
92+
* client via `current_mode_update` notifications.
93+
*
94+
* See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
95+
*
96+
* @param request The set mode request with session ID and mode ID
97+
* @return Set session mode response
6198
*/
62-
public suspend fun loadSession(request: LoadSessionRequest)
99+
public suspend fun sessionSetMode(request: SetSessionModeRequest): SetSessionModeResponse
63100

64101
/**
65102
* Process a user prompt within a session.
66103
*
67-
* This is the main method for handling user interactions. The agent should:
68-
* 1. Process the prompt content
69-
* 2. Send session updates via the client connection
70-
* 3. Execute any necessary tool calls (with permission if needed)
71-
* 4. Return a final response with the stop reason
104+
* This method handles the full lifecycle of a prompt turn:
105+
* 1. Receives user messages with optional context (files, images, etc.)
106+
* 2. Processes the prompt using language models
107+
* 3. Reports language model content and tool calls to the client via [sessionUpdate]
108+
* 4. Requests permission to run tools via client's [sessionRequestPermission]
109+
* 5. Executes approved tool calls
110+
* 6. Returns when the turn is complete with a stop reason
111+
*
112+
* See protocol docs: [Prompt Turn](https://agentclientprotocol.com/protocol/prompt-turn)
72113
*
73-
* See protocol docs: [User Message](https://agentclientprotocol.com/protocol/prompt-turn#1-user-message)
114+
* @param request The prompt request with session ID and content blocks
115+
* @return The stop reason (end_turn, max_tokens, max_turn_requests, refusal, or cancelled)
74116
*/
75-
public suspend fun prompt(request: PromptRequest): PromptResponse
117+
public suspend fun sessionPrompt(request: PromptRequest): PromptResponse
76118

77119
/**
78120
* Cancel ongoing operations for a session.
79121
*
80-
* The client sends this notification to request cancellation of the current
81-
* prompt turn. The agent should stop processing and return a cancelled response.
122+
* This is a notification sent by the client to cancel an ongoing prompt turn.
123+
* Upon receiving this notification, the agent should:
124+
* - Stop all language model requests as soon as possible
125+
* - Abort all tool call invocations in progress
126+
* - Send any pending session update notifications
127+
* - Respond to the original [sessionPrompt] request with `StopReason.CANCELLED`
82128
*
83129
* See protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/prompt-turn#cancellation)
130+
*
131+
* @param notification The cancellation notification with session ID
84132
*/
85-
public suspend fun cancel(notification: CancelNotification)
133+
public suspend fun sessionCancel(notification: CancelNotification)
86134
}

kotlin/kotlin-acp/src/commonMain/kotlin/io/agentclientprotocol/agent/AgentSideConnection.kt

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ public class AgentSideConnection(
5353
} else {
5454
throw IllegalArgumentException("authenticate requires parameters")
5555
}
56-
agent.authenticate(params)
57-
JsonNull // No response body for authenticate
56+
val response = agent.authenticate(params)
57+
ACPJson.encodeToJsonElement(response)
5858
}
5959

6060
protocol.setRequestHandler(AgentMethods.SESSION_NEW) { request ->
@@ -63,7 +63,7 @@ public class AgentSideConnection(
6363
} else {
6464
throw IllegalArgumentException("session/new requires parameters")
6565
}
66-
val response = agent.newSession(params)
66+
val response = agent.sessionNew(params)
6767
ACPJson.encodeToJsonElement(response)
6868
}
6969

@@ -73,27 +73,37 @@ public class AgentSideConnection(
7373
} else {
7474
throw IllegalArgumentException("session/load requires parameters")
7575
}
76-
agent.loadSession(params)
77-
JsonNull // No response body for loadSession
76+
val response = agent.sessionLoad(params)
77+
ACPJson.encodeToJsonElement(response)
78+
}
79+
80+
protocol.setRequestHandler(AgentMethods.SESSION_SET_MODE) { request ->
81+
val params = if (request.params != null) {
82+
ACPJson.decodeFromJsonElement<SetSessionModeRequest>(request.params)
83+
} else {
84+
throw IllegalArgumentException("session/set_mode requires parameters")
85+
}
86+
val response = agent.sessionSetMode(params)
87+
ACPJson.encodeToJsonElement(response)
7888
}
7989

8090
protocol.setRequestHandler(AgentMethods.SESSION_PROMPT) { request ->
8191
val params = if (request.params != null) {
8292
ACPJson.decodeFromJsonElement<PromptRequest>(request.params)
8393
} else {
84-
throw IllegalArgumentException("session/prompt requires parameters")
94+
throw IllegalArgumentException("session/sessionPrompt requires parameters")
8595
}
86-
val response = agent.prompt(params)
96+
val response = agent.sessionPrompt(params)
8797
ACPJson.encodeToJsonElement(response)
8898
}
8999

90100
protocol.setNotificationHandler(AgentMethods.SESSION_CANCEL) { notification ->
91101
val params = if (notification.params != null) {
92102
ACPJson.decodeFromJsonElement<CancelNotification>(notification.params)
93103
} else {
94-
throw IllegalArgumentException("session/cancel requires parameters")
104+
throw IllegalArgumentException("session/sessionCancel requires parameters")
95105
}
96-
agent.cancel(params)
106+
agent.sessionCancel(params)
97107
}
98108

99109
protocol.start()
@@ -105,20 +115,52 @@ public class AgentSideConnection(
105115
protocol.sendNotification(ClientMethods.SESSION_UPDATE, params)
106116
}
107117

108-
override suspend fun requestPermission(request: RequestPermissionRequest): RequestPermissionResponse {
118+
override suspend fun sessionRequestPermission(request: RequestPermissionRequest): RequestPermissionResponse {
109119
val params = ACPJson.encodeToJsonElement(request)
110120
val responseJson = protocol.sendRequest(ClientMethods.SESSION_REQUEST_PERMISSION, params)
111121
return ACPJson.decodeFromJsonElement(responseJson)
112122
}
113123

114-
override suspend fun readTextFile(request: ReadTextFileRequest): ReadTextFileResponse {
124+
override suspend fun fsReadTextFile(request: ReadTextFileRequest): ReadTextFileResponse {
115125
val params = ACPJson.encodeToJsonElement(request)
116126
val responseJson = protocol.sendRequest(ClientMethods.FS_READ_TEXT_FILE, params)
117127
return ACPJson.decodeFromJsonElement(responseJson)
118128
}
119129

120-
override suspend fun writeTextFile(request: WriteTextFileRequest) {
130+
override suspend fun fsWriteTextFile(request: WriteTextFileRequest): WriteTextFileResponse {
131+
val params = ACPJson.encodeToJsonElement(request)
132+
val responseJson = protocol.sendRequest(ClientMethods.FS_WRITE_TEXT_FILE, params)
133+
return ACPJson.decodeFromJsonElement(responseJson)
134+
}
135+
136+
override suspend fun terminalCreate(request: CreateTerminalRequest): CreateTerminalResponse {
137+
val params = ACPJson.encodeToJsonElement(request)
138+
val responseJson = protocol.sendRequest(ClientMethods.TERMINAL_CREATE, params)
139+
return ACPJson.decodeFromJsonElement(responseJson)
140+
}
141+
142+
override suspend fun terminalOutput(request: TerminalOutputRequest): TerminalOutputResponse {
143+
val params = ACPJson.encodeToJsonElement(request)
144+
val responseJson = protocol.sendRequest(ClientMethods.TERMINAL_OUTPUT, params)
145+
return ACPJson.decodeFromJsonElement(responseJson)
146+
}
147+
148+
override suspend fun terminalRelease(request: ReleaseTerminalRequest): ReleaseTerminalResponse {
121149
val params = ACPJson.encodeToJsonElement(request)
122-
protocol.sendRequest(ClientMethods.FS_WRITE_TEXT_FILE, params)
150+
val responseJson = protocol.sendRequest(ClientMethods.TERMINAL_RELEASE, params)
151+
return ACPJson.decodeFromJsonElement(responseJson)
152+
}
153+
154+
override suspend fun terminalWaitForExit(request: WaitForTerminalExitRequest): WaitForTerminalExitResponse {
155+
val params = ACPJson.encodeToJsonElement(request)
156+
val responseJson = protocol.sendRequest(ClientMethods.TERMINAL_WAIT_FOR_EXIT, params)
157+
return ACPJson.decodeFromJsonElement(responseJson)
158+
}
159+
160+
override suspend fun terminalKill(request: KillTerminalCommandRequest): KillTerminalCommandResponse {
161+
val params = ACPJson.encodeToJsonElement(request)
162+
val responseJson = protocol.sendRequest(ClientMethods.TERMINAL_KILL, params)
163+
164+
return ACPJson.decodeFromJsonElement(responseJson)
123165
}
124166
}

kotlin/kotlin-acp/src/commonMain/kotlin/io/agentclientprotocol/client/Client.kt

Lines changed: 84 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
11
package io.agentclientprotocol.client
22

3+
import io.agentclientprotocol.model.CreateTerminalRequest
4+
import io.agentclientprotocol.model.CreateTerminalResponse
5+
import io.agentclientprotocol.model.KillTerminalCommandRequest
6+
import io.agentclientprotocol.model.KillTerminalCommandResponse
37
import io.agentclientprotocol.model.ReadTextFileRequest
48
import io.agentclientprotocol.model.ReadTextFileResponse
9+
import io.agentclientprotocol.model.ReleaseTerminalRequest
10+
import io.agentclientprotocol.model.ReleaseTerminalResponse
511
import io.agentclientprotocol.model.RequestPermissionRequest
612
import io.agentclientprotocol.model.RequestPermissionResponse
713
import io.agentclientprotocol.model.SessionNotification
14+
import io.agentclientprotocol.model.TerminalOutputRequest
15+
import io.agentclientprotocol.model.TerminalOutputResponse
16+
import io.agentclientprotocol.model.WaitForTerminalExitRequest
17+
import io.agentclientprotocol.model.WaitForTerminalExitResponse
818
import io.agentclientprotocol.model.WriteTextFileRequest
19+
import io.agentclientprotocol.model.WriteTextFileResponse
920

1021
/**
1122
* Interface that clients must implement to handle agent requests.
@@ -25,7 +36,7 @@ public interface Client {
2536
* @param request The file read request containing path and optional line/limit
2637
* @return The file contents
2738
*/
28-
public suspend fun readTextFile(request: ReadTextFileRequest): ReadTextFileResponse
39+
public suspend fun fsReadTextFile(request: ReadTextFileRequest): ReadTextFileResponse
2940

3041
/**
3142
* Write content to a text file in the client's file system.
@@ -34,8 +45,9 @@ public interface Client {
3445
* The client should validate the path and ensure it's within allowed boundaries.
3546
*
3647
* @param request The file write request containing path and content
48+
* @return Write text file response
3749
*/
38-
public suspend fun writeTextFile(request: WriteTextFileRequest)
50+
public suspend fun fsWriteTextFile(request: WriteTextFileRequest): WriteTextFileResponse
3951

4052
/**
4153
* Request permission from the user for a tool call operation.
@@ -46,7 +58,7 @@ public interface Client {
4658
* @param request The permission request with tool call details and options
4759
* @return The user's permission decision
4860
*/
49-
public suspend fun requestPermission(request: RequestPermissionRequest): RequestPermissionResponse
61+
public suspend fun sessionRequestPermission(request: RequestPermissionRequest): RequestPermissionResponse
5062

5163
/**
5264
* Handle session update notifications from the agent.
@@ -58,4 +70,73 @@ public interface Client {
5870
* @param notification The session update notification
5971
*/
6072
public suspend fun sessionUpdate(notification: SessionNotification)
73+
74+
/**
75+
* Creates a new terminal to execute a command.
76+
*
77+
* Only called if the client advertises the `terminal` capability.
78+
* The agent must call [terminalRelease] when done with the terminal to free resources.
79+
*
80+
* See protocol docs: [Terminal Documentation](https://agentclientprotocol.com/protocol/terminals)
81+
*
82+
* @param request The terminal creation request containing command, args, and environment
83+
* @return The created terminal's ID
84+
*/
85+
public suspend fun terminalCreate(request: CreateTerminalRequest): CreateTerminalResponse
86+
87+
/**
88+
* Gets the current output and exit status of a terminal.
89+
*
90+
* Returns immediately without waiting for the command to complete.
91+
* If the command has already exited, the exit status is included in the response.
92+
*
93+
* See protocol docs: [Getting Terminal Output](https://agentclientprotocol.com/protocol/terminals#getting-output)
94+
*
95+
* @param request The terminal output request with terminal ID
96+
* @return The terminal output, truncation status, and optional exit status
97+
*/
98+
public suspend fun terminalOutput(request: TerminalOutputRequest): TerminalOutputResponse
99+
100+
/**
101+
* Releases a terminal and frees all associated resources.
102+
*
103+
* The command is killed if it hasn't exited yet. After release, the terminal ID
104+
* becomes invalid for all other terminal methods. Tool calls that already contain
105+
* the terminal ID continue to display its output.
106+
*
107+
* See protocol docs: [Releasing Terminals](https://agentclientprotocol.com/protocol/terminals#releasing-terminals)
108+
*
109+
* @param request The release terminal request with terminal ID
110+
* @return Release terminal response
111+
*/
112+
public suspend fun terminalRelease(request: ReleaseTerminalRequest): ReleaseTerminalResponse
113+
114+
/**
115+
* Waits for a terminal command to exit and returns its exit status.
116+
*
117+
* This method blocks until the command completes, providing the exit code
118+
* and/or signal that terminated the process.
119+
*
120+
* See protocol docs: [Waiting for Exit](https://agentclientprotocol.com/protocol/terminals#waiting-for-exit)
121+
*
122+
* @param request The wait for exit request with terminal ID
123+
* @return The exit code and/or signal
124+
*/
125+
public suspend fun terminalWaitForExit(request: WaitForTerminalExitRequest): WaitForTerminalExitResponse
126+
127+
/**
128+
* Kills a terminal command without releasing the terminal.
129+
*
130+
* While [terminalRelease] also kills the command, this method keeps the terminal ID
131+
* valid so it can be used with other methods. Useful for implementing command timeouts
132+
* that terminate the command and then retrieve the final output.
133+
*
134+
* Note: Call [terminalRelease] when the terminal is no longer needed.
135+
*
136+
* See protocol docs: [Killing Commands](https://agentclientprotocol.com/protocol/terminals#killing-commands)
137+
*
138+
* @param request The kill terminal request with terminal ID
139+
* @return Kill terminal response
140+
*/
141+
public suspend fun terminalKill(request: KillTerminalCommandRequest): KillTerminalCommandResponse
61142
}

0 commit comments

Comments
 (0)