ACPex.Client behaviour (ACPex v0.1.0)

View Source

Behaviour for implementing an ACP client (typically a code editor).

A client is responsible for:

  • Managing the connection to an agent
  • Handling session updates from the agent
  • Responding to agent requests for file system and terminal operations

Type-Safe API

All callbacks use strongly-typed structs from the ACPex.Schema.* modules, providing compile-time validation and better documentation.

Example

defmodule MyEditor do
  @behaviour ACPex.Client

  def init(_args), do: {:ok, %{files: %{}}}

  def handle_session_update(notification, state) do
    # Display update in UI
    {:noreply, state}
  end

  def handle_fs_read_text_file(request, state) do
    case File.read(request.path) do
      {:ok, content} ->
        response = %ACPex.Schema.Client.FsReadTextFileResponse{
          content: content
        }
        {:ok, response, state}

      {:error, _} ->
        {:error, %{code: -32001, message: "File not found"}, state}
    end
  end

  # ... other callbacks
end

Summary

Callbacks

Handle a request from the agent to read a text file.

Handle a request from the agent to write a text file.

Handle a session update notification from the agent.

Handle a request from the agent to create a terminal.

Handle a request from the agent to kill a terminal command.

Handle a request from the agent to get terminal output.

Handle a request from the agent to release a terminal.

Handle a request from the agent to wait for terminal exit.

Initialize the client with the given arguments.

Types

error_response()

@type error_response() :: %{code: integer(), message: String.t()}

state()

@type state() :: term()

Callbacks

handle_fs_read_text_file(t, state)

@callback handle_fs_read_text_file(ACPex.Schema.Client.FsReadTextFileRequest.t(), state()) ::
  {:ok, ACPex.Schema.Client.FsReadTextFileResponse.t(), state()}
  | {:error, error_response(), state()}

Handle a request from the agent to read a text file.

Parameters

  • request - A FsReadTextFileRequest struct with the file path
  • state - Current client state

Returns

  • {:ok, response, new_state} where response is a FsReadTextFileResponse struct
  • {:error, error_map, new_state} if file cannot be read

handle_fs_write_text_file(t, state)

@callback handle_fs_write_text_file(
  ACPex.Schema.Client.FsWriteTextFileRequest.t(),
  state()
) ::
  {:ok, ACPex.Schema.Client.FsWriteTextFileResponse.t(), state()}
  | {:error, error_response(), state()}

Handle a request from the agent to write a text file.

Parameters

  • request - A FsWriteTextFileRequest struct with path and content
  • state - Current client state

Returns

  • {:ok, response, new_state} where response is a FsWriteTextFileResponse struct
  • {:error, error_map, new_state} if file cannot be written

handle_session_update(t, state)

@callback handle_session_update(ACPex.Schema.Session.UpdateNotification.t(), state()) ::
  {:noreply, state()}

Handle a session update notification from the agent.

These are streaming updates during prompt processing (thoughts, message chunks, tool calls, etc).

Parameters

  • notification - An UpdateNotification struct with session_id and update data
  • state - Current client state

Returns

  • {:noreply, new_state} - Notifications don't send responses

handle_terminal_create(t, state)

Handle a request from the agent to create a terminal.

Parameters

  • request - A CreateRequest struct with terminal configuration
  • state - Current client state

Returns

  • {:ok, response, new_state} where response is a CreateResponse struct with terminal_id
  • {:error, error_map, new_state} if terminal cannot be created

handle_terminal_kill(t, state)

@callback handle_terminal_kill(ACPex.Schema.Client.Terminal.KillRequest.t(), state()) ::
  {:ok, ACPex.Schema.Client.Terminal.KillResponse.t(), state()}
  | {:error, error_response(), state()}

Handle a request from the agent to kill a terminal command.

Parameters

  • request - A KillRequest struct with terminal_id
  • state - Current client state

Returns

  • {:ok, response, new_state} where response is a KillResponse struct
  • {:error, error_map, new_state} if terminal not found

handle_terminal_output(t, state)

Handle a request from the agent to get terminal output.

Parameters

  • request - An OutputRequest struct with terminal_id
  • state - Current client state

Returns

  • {:ok, response, new_state} where response is an OutputResponse struct with output data
  • {:error, error_map, new_state} if terminal not found

handle_terminal_release(t, state)

@callback handle_terminal_release(
  ACPex.Schema.Client.Terminal.ReleaseRequest.t(),
  state()
) ::
  {:ok, ACPex.Schema.Client.Terminal.ReleaseResponse.t(), state()}
  | {:error, error_response(), state()}

Handle a request from the agent to release a terminal.

Parameters

  • request - A ReleaseRequest struct with terminal_id
  • state - Current client state

Returns

  • {:ok, response, new_state} where response is a ReleaseResponse struct
  • {:error, error_map, new_state} if terminal not found

handle_terminal_wait_for_exit(t, state)

@callback handle_terminal_wait_for_exit(
  ACPex.Schema.Client.Terminal.WaitForExitRequest.t(),
  state()
) ::
  {:ok, ACPex.Schema.Client.Terminal.WaitForExitResponse.t(), state()}
  | {:error, error_response(), state()}

Handle a request from the agent to wait for terminal exit.

Parameters

  • request - A WaitForExitRequest struct with terminal_id
  • state - Current client state

Returns

  • {:ok, response, new_state} where response is a WaitForExitResponse struct with exit status
  • {:error, error_map, new_state} if terminal not found

init(args)

@callback init(args :: term()) :: {:ok, state()}

Initialize the client with the given arguments.

Returns {:ok, initial_state}.