Agent Client Protocol agent over stdio: bin/super-pi acp.
Editors (Zed, JetBrains, GitHub Copilot CLI, the neovim plugins) start the agent as a subprocess and
speak JSON-RPC 2.0, one message per line. ACP is bidirectional: the agent also sends requests
(session/request_permission, fs/read_text_file) and waits for the answer. So this is not
SuperPi.RPC.Server: that module only replies and notifies and has no table of outstanding
requests. Here a pending table maps each outgoing request id to what waits for it.
Methods
| ACP | Super-Pi |
|---|---|
initialize | Agent capabilities, authMethods from Auth.required?/0, harness capabilities in _meta.superPi.harnesses |
authenticate | The token store of auth.login (token in _meta.token or SUPER_PI_GATEWAY_TOKEN) |
session/new | A conversation with workspacePaths: [cwd]. _meta.harness picks the harness. mcpServers are applied to the MCP manager |
session/load | Resume (not fork): replays history as session/update notifications, then answers |
_superpi/session/fork | Fork at the latest entry into a new session (ACP's _ convention for custom methods) |
session/prompt | Submits in a supervised task, so session/cancel can arrive during the prompt |
session/cancel | UI.Broker.cancel_pending/1, then Machine.cancel/1, in that order |
session/set_mode | Sets executionMode within the remote ceiling and the harness ceiling |
stopReason: end_turn for a finished turn, cancelled for a cancel, refusal for an error (the
error text goes to the client as a message chunk first).
Terminals and files
terminal/* is never delegated: SandboxRunner gives process-group kill, output spill and the
sandbox, and an editor terminal gives none of that and bypasses permissions.deny. A running command
is a tool_call of kind execute.
config :super_pi, :acp, fs_delegation: :unsaved_only | :never | :always (default
:unsaved_only). fs/read_text_file returns the unsaved editor buffer, the only reason to delegate.
SuperPi.Env.ClientFS asks the client only when the client advertised the method, the machine runs
on this node (the editor's files do not exist on another node) and the path is inside the
workspace. Writes always stay on the server.
Transport
run_stdio/1 starts the server and reads standard input. Output is one JSON object per line on
standard output, so logs must go to standard error (SUPER_PI_LOG_STDERR=1, set by bin/super-pi).
For tests, start_link(send: fun) and send(server, {:acp_line, line}).
Summary
Functions
Returns a specification to start this module under a supervisor.
Asks the client for the text of a file, including unsaved changes. Used by SuperPi.Env.ClientFS.
Starts the server on standard input and output and returns when the input ends.
Functions
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec read_text_file(pid(), integer(), String.t(), keyword()) :: {:ok, String.t()} | {:error, term()}
Asks the client for the text of a file, including unsaved changes. Used by SuperPi.Env.ClientFS.
Starts the server on standard input and output and returns when the input ends.