// The two contracts a user implements: one to be an agent, one to be a client. Anything left out
// keeps the default body, which raises `Unsupported` and travels as -32601, so an agent only
// declares in `initialize` what it actually answers.
///|
/// The agent side. Implement what the agent can do and leave the rest: `initialize` and
/// `new_session` and `prompt` are the three every agent has, the others have defaults that report
/// themselves as unsupported.
pub(open) trait Agent {
///|
/// Negotiates the version and trades capabilities. Called once per connection, before anything
/// else.
async fn initialize(Self, Initialize) -> Initialized raise Refused
///|
/// Runs the agent's own authentication flow for the method the client picked.
async fn authenticate(Self, Authenticate) -> Unit raise Refused = _
///|
/// Drops whatever `authenticate` established.
async fn logout(Self) -> Unit raise Refused = _
///|
/// Starts a session in `cwd`. The working directories and MCP servers come from the client.
async fn new_session(Self, NewSession) -> SessionStarted raise Refused
///|
/// Reopens a session and replays its history through the `Session` handle before answering.
async fn load_session(Self, LoadSession, Session) -> SessionStarted raise Refused = _
///|
/// Reattaches to a live session without replaying anything.
async fn resume_session(Self, ResumeSession, Session) -> SessionStarted raise Refused = _
///|
/// The sessions this agent remembers.
async fn list_sessions(Self, ListSessions) -> SessionList raise Refused = _
///|
/// Forgets a session.
async fn delete_session(Self, DeleteSession) -> Unit raise Refused = _
///|
/// Ends a running session and frees what it holds.
async fn close_session(Self, CloseSession) -> Unit raise Refused = _
///|
/// Switches the session's mode.
async fn set_mode(Self, SetMode) -> Unit raise Refused = _
///|
/// Sets one configuration option and answers with the whole option list.
async fn set_config_option(Self, SetConfigOption) -> Array[ConfigOption] raise Refused = _
///|
/// Runs one turn. Updates go out through the `Session`, and the answer says why the turn ended.
/// `session/cancel` cancels the task this runs in, so an await is where a turn can be stopped.
async fn prompt(Self, Prompt, Session) -> StopReason raise Refused
///|
/// The client asked for the turn in `id` to stop. Called from the read loop: return quickly, and
/// do not wait for the turn.
async fn cancel(Self, id : String) -> Unit = _
}
///|
impl Agent with fn authenticate(self, request) {
ignore(self)
ignore(request)
raise Refused::Unsupported(name="authenticate")
}
///|
impl Agent with fn logout(self) {
ignore(self)
raise Refused::Unsupported(name="logout")
}
///|
impl Agent with fn load_session(self, request, session) {
ignore(self)
ignore(request)
ignore(session)
raise Refused::Unsupported(name="session/load")
}
///|
impl Agent with fn resume_session(self, request, session) {
ignore(self)
ignore(request)
ignore(session)
raise Refused::Unsupported(name="session/resume")
}
///|
impl Agent with fn list_sessions(self, request) {
ignore(self)
ignore(request)
raise Refused::Unsupported(name="session/list")
}
///|
impl Agent with fn delete_session(self, request) {
ignore(self)
ignore(request)
raise Refused::Unsupported(name="session/delete")
}
///|
impl Agent with fn close_session(self, request) {
ignore(self)
ignore(request)
raise Refused::Unsupported(name="session/close")
}
///|
impl Agent with fn set_mode(self, request) {
ignore(self)
ignore(request)
raise Refused::Unsupported(name="session/set_mode")
}
///|
impl Agent with fn set_config_option(self, request) {
ignore(self)
ignore(request)
raise Refused::Unsupported(name="session/set_config_option")
}
///|
impl Agent with fn cancel(self, id) {
ignore(self)
ignore(id)
}
///|
/// The client side. `update` is the only method the protocol requires; the rest exist so the agent
/// can ask for them, and a client that leaves one out answers -32601 when the agent asks.
pub(open) trait Client {
///|
/// One update from the agent. Notifications are not answered, so a failure here is the client's
/// own business; it must not stop the turn.
async fn update(Self, String, SessionUpdate) -> Unit
///|
/// The user is asked whether a tool call may run.
async fn request_permission(Self, Permission) -> Outcome raise Refused
///|
/// Reads a text file the agent wants to see.
async fn read_text_file(Self, ReadTextFile) -> String raise Refused = _
///|
/// Writes a text file the agent produced.
async fn write_text_file(Self, WriteTextFile) -> Unit raise Refused = _
///|
/// Starts a command and gives back its terminal identifier.
async fn create_terminal(Self, TerminalCommand) -> String raise Refused = _
///|
/// Everything the terminal has printed so far.
async fn terminal_output(Self, TerminalRequest) -> TerminalOutput raise Refused = _
///|
/// Waits for the command in a terminal to exit.
async fn wait_for_terminal_exit(Self, TerminalRequest) -> ExitStatus raise Refused = _
///|
/// Stops the command without giving the terminal back.
async fn kill_terminal(Self, TerminalRequest) -> Unit raise Refused = _
///|
/// Gives the terminal back.
async fn release_terminal(Self, TerminalRequest) -> Unit raise Refused = _
///|
/// Puts a form or a link in front of the user.
async fn elicit(Self, Elicitation) -> Answer raise Refused = _
}
///|
impl Client with fn read_text_file(self, request) {
ignore(self)
ignore(request)
raise Refused::Unsupported(name="fs/read_text_file")
}
///|
impl Client with fn write_text_file(self, request) {
ignore(self)
ignore(request)
raise Refused::Unsupported(name="fs/write_text_file")
}
///|
impl Client with fn create_terminal(self, request) {
ignore(self)
ignore(request)
raise Refused::Unsupported(name="terminal/create")
}
///|
impl Client with fn terminal_output(self, request) {
ignore(self)
ignore(request)
raise Refused::Unsupported(name="terminal/output")
}
///|
impl Client with fn wait_for_terminal_exit(self, request) {
ignore(self)
ignore(request)
raise Refused::Unsupported(name="terminal/wait_for_exit")
}
///|
impl Client with fn kill_terminal(self, request) {
ignore(self)
ignore(request)
raise Refused::Unsupported(name="terminal/kill")
}
///|
impl Client with fn release_terminal(self, request) {
ignore(self)
ignore(request)
raise Refused::Unsupported(name="terminal/release")
}
///|
impl Client with fn elicit(self, request) {
ignore(self)
ignore(request)
raise Refused::Unsupported(name="elicitation/create")
}