acp

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 2, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package acp implements the Agent Client Protocol (ACP) surface for ZERO: a JSON-RPC 2.0 peer spoken over stdio (newline-delimited JSON) so editors such as Zed, JetBrains, and Neovim can drive ZERO's agent core as a backend.

The protocol shapes (method names, message fields) are derived solely from the public, Apache-licensed ACP specification at agentclientprotocol.com and the agentclientprotocol/agent-client-protocol repository (schema/v1). All logic here is written originally against ZERO's own interfaces.

Index

Constants

View Source
const (
	MethodInitialize             = "initialize"
	MethodAuthenticate           = "authenticate"
	MethodSessionNew             = "session/new"
	MethodSessionLoad            = "session/load"
	MethodSessionPrompt          = "session/prompt"
	MethodSessionCancel          = "session/cancel" // notification
	MethodSessionUpdate          = "session/update" // notification (agent -> client)
	MethodSessionSetMode         = "session/set_mode"
	MethodSessionSetConfigOption = "session/set_config_option"
	MethodSessionRequestPerm     = "session/request_permission" // agent -> client
	MethodFSReadTextFile         = "fs/read_text_file"          // agent -> client
	MethodFSWriteTextFile        = "fs/write_text_file"         // agent -> client

	// Vendor-prefixed ZERO extensions (clients that don't support them ignore the
	// method and degrade cleanly, per the spec's _-prefixed convention).
	MethodZeroSetModel = "_zero/set_model"
)

Method names exactly as they appear on the wire (public ACP spec).

View Source
const (
	UpdateAgentMessageChunk = "agent_message_chunk"
	UpdateAgentThoughtChunk = "agent_thought_chunk"
	UpdateUserMessageChunk  = "user_message_chunk"
	UpdateToolCall          = "tool_call"
	UpdateToolCallUpdate    = "tool_call_update"
	UpdatePlan              = "plan"
	UpdateAvailableCommands = "available_commands_update"
	UpdateCurrentMode       = "current_mode_update"
)

SessionUpdate discriminator values (the "sessionUpdate" field).

View Source
const (
	StopEndTurn   = "end_turn"
	StopMaxTokens = "max_tokens"
	StopRefusal   = "refusal"
	StopCancelled = "cancelled"
)

StopReason values (why a prompt turn ended).

View Source
const (
	ToolKindRead    = "read"
	ToolKindEdit    = "edit"
	ToolKindDelete  = "delete"
	ToolKindMove    = "move"
	ToolKindSearch  = "search"
	ToolKindExecute = "execute"
	ToolKindThink   = "think"
	ToolKindFetch   = "fetch"
	ToolKindOther   = "other"
)

ToolKind classifies a tool call for client rendering.

View Source
const (
	ToolStatusPending    = "pending"
	ToolStatusInProgress = "in_progress"
	ToolStatusCompleted  = "completed"
	ToolStatusFailed     = "failed"
)

ToolCallStatus values.

View Source
const (
	PlanStatusPending    = "pending"
	PlanStatusInProgress = "in_progress"
	PlanStatusCompleted  = "completed"

	PlanPriorityHigh   = "high"
	PlanPriorityMedium = "medium"
	PlanPriorityLow    = "low"
)
View Source
const (
	PermAllowOnce    = "allow_once"
	PermAllowAlways  = "allow_always"
	PermRejectOnce   = "reject_once"
	PermRejectAlways = "reject_always"
)
View Source
const (
	OutcomeSelected  = "selected"
	OutcomeCancelled = "cancelled"
)
View Source
const ProtocolVersion = 1

ProtocolVersion is the ACP protocol version ZERO speaks. Wire compatibility is negotiated during initialize; v1 is the current stable version.

Variables

This section is empty.

Functions

func RPCError

func RPCError(code int, message string) error

RPCError builds a protocol error to return from a handler. Use it when a handler needs to control the wire-level error code; any other error a handler returns is reported as a generic internal error.

Types

type Agent

type Agent struct {
	// contains filtered or unexported fields
}

Agent is the ACP agent server bound to one JSON-RPC connection (one editor).

func NewAgent

func NewAgent(conn *Conn, deps Deps) *Agent

NewAgent builds the ACP server and registers its method handlers on conn.

func (*Agent) Serve

func (a *Agent) Serve(ctx context.Context) error

Serve runs the connection read loop until the stream closes or ctx is done.

type AgentCapabilities

type AgentCapabilities struct {
	LoadSession        bool               `json:"loadSession"`
	PromptCapabilities PromptCapabilities `json:"promptCapabilities"`
}

type AuthMethod

type AuthMethod struct {
	ID          string `json:"id"`
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`
}

type AvailableCommand

type AvailableCommand struct {
	Name        string `json:"name"`
	Description string `json:"description"`
}

type AvailableCommandsUpdate

type AvailableCommandsUpdate struct {
	SessionUpdate     string             `json:"sessionUpdate"`
	AvailableCommands []AvailableCommand `json:"availableCommands"`
}

type CancelParams

type CancelParams struct {
	SessionID string `json:"sessionId"`
}

type ClientCapabilities

type ClientCapabilities struct {
	FS       FileSystemCapabilities `json:"fs"`
	Terminal bool                   `json:"terminal"`
}

type Conn

type Conn struct {
	// contains filtered or unexported fields
}

Conn is a JSON-RPC 2.0 peer over a single ndjson stream pair. It both serves inbound requests/notifications (via registered handlers) and issues outbound requests/notifications — needed because ACP is bidirectional (the agent calls the client for session/request_permission, fs/*, terminal/*).

func NewConn

func NewConn(r io.Reader, w io.Writer) *Conn

NewConn builds a peer reading ndjson from r and writing ndjson to w.

func (*Conn) Call

func (c *Conn) Call(ctx context.Context, method string, params any, result any) error

Call issues an outbound request and blocks until the response arrives, ctx is cancelled, or the connection closes.

func (*Conn) Handle

func (c *Conn) Handle(method string, fn HandlerFunc)

Handle registers a request handler for method.

func (*Conn) HandleNotify

func (c *Conn) HandleNotify(method string, fn NotifyFunc)

HandleNotify registers a notification handler for method.

func (*Conn) Notify

func (c *Conn) Notify(method string, params any) error

Notify issues an outbound notification (no response expected).

func (*Conn) Serve

func (c *Conn) Serve(ctx context.Context) error

Serve runs the read loop until the stream ends, ctx is cancelled, or a fatal decode error occurs. Inbound requests and notifications are dispatched on their own goroutines so a long-running handler (e.g. session/prompt) never blocks the loop from delivering session/cancel or a permission response.

type ContentBlock

type ContentBlock struct {
	Type     string          `json:"type"`
	Text     string          `json:"text,omitempty"`
	Data     string          `json:"data,omitempty"`     // image/audio: base64
	MimeType string          `json:"mimeType,omitempty"` // image/audio
	URI      string          `json:"uri,omitempty"`      // resource_link
	Name     string          `json:"name,omitempty"`     // resource_link
	Resource json.RawMessage `json:"resource,omitempty"` // embedded resource
}

ContentBlock is the polymorphic content type. ZERO emits "text" (and "image" on tool content); it parses "text", "image", and "resource"/"resource_link" from inbound prompts. A single struct with omitempty fields covers both directions since the field names do not collide across the variants ZERO uses.

func ImageBlock

func ImageBlock(base64Data, mimeType string) ContentBlock

func TextBlock

func TextBlock(text string) ContentBlock

type ContentChunk

type ContentChunk struct {
	SessionUpdate string       `json:"sessionUpdate"`
	Content       ContentBlock `json:"content"`
}

AgentMessageChunk / AgentThoughtChunk / UserMessageChunk all carry a single ContentBlock under "content"; the variant is set via SessionUpdate.

type CurrentModeUpdate

type CurrentModeUpdate struct {
	SessionUpdate string `json:"sessionUpdate"`
	CurrentModeID string `json:"currentModeId"`
}

type Deps

type Deps struct {
	ResolveConfig func(workspaceRoot string, overrides config.Overrides) (config.ResolvedConfig, error)
	NewProvider   func(profile config.ProviderProfile) (zeroruntime.Provider, error)
	RunAgent      func(ctx context.Context, prompt string, provider zeroruntime.Provider, opts agent.Options) (agent.Result, error)
	// BuildWorkspace builds the SCOPED tool registry and the sandbox engine for a
	// validated workspace root, so ACP shell tools (bash/exec_command) are confined
	// exactly like the exec surface — never run unconfined on the host.
	BuildWorkspace func(workspaceRoot string, resolved config.ResolvedConfig) (*tools.Registry, *sandbox.Engine, error)
	// ResolveWorkspaceRoot validates + normalizes a client-supplied cwd (must be an
	// existing directory; never the bare root). It is the file-tool confinement root.
	ResolveWorkspaceRoot func(cwd string) (string, error)
	Store                *sessions.Store
	AgentInfo            Implementation
}

Deps are the ZERO capabilities the ACP Agent drives. The CLI fills these with real implementations; tests inject fakes (e.g. a canned provider) to drive the full ACP flow without a live model. Keeping auth/model/keys behind these deps means the editor only hosts the thread — ZERO owns BYOK and telemetry-free operation.

type FileSystemCapabilities

type FileSystemCapabilities struct {
	ReadTextFile  bool `json:"readTextFile"`
	WriteTextFile bool `json:"writeTextFile"`
}

type HandlerFunc

type HandlerFunc func(ctx context.Context, params json.RawMessage) (any, error)

HandlerFunc handles an inbound request and returns the result to encode, or an error. Returning an *rpcError controls the wire code; any other error becomes a generic internal error.

type Implementation

type Implementation struct {
	Name    string `json:"name"`
	Version string `json:"version,omitempty"`
}

type InitializeParams

type InitializeParams struct {
	ProtocolVersion    int                `json:"protocolVersion"`
	ClientCapabilities ClientCapabilities `json:"clientCapabilities"`
	ClientInfo         *Implementation    `json:"clientInfo,omitempty"`
}

type InitializeResult

type InitializeResult struct {
	ProtocolVersion   int               `json:"protocolVersion"`
	AgentCapabilities AgentCapabilities `json:"agentCapabilities"`
	AgentInfo         *Implementation   `json:"agentInfo,omitempty"`
	AuthMethods       []AuthMethod      `json:"authMethods"`
}

type LoadSessionParams

type LoadSessionParams struct {
	SessionID             string      `json:"sessionId"`
	Cwd                   string      `json:"cwd"`
	McpServers            []McpServer `json:"mcpServers"`
	AdditionalDirectories []string    `json:"additionalDirectories,omitempty"`
}

type LoadSessionResult

type LoadSessionResult struct {
	ConfigOptions []SessionConfigOption `json:"configOptions,omitempty"`
	Modes         *SessionModeState     `json:"modes,omitempty"`
}

type McpServer

type McpServer struct {
	Name    string          `json:"name"`
	Command string          `json:"command,omitempty"`
	Args    []string        `json:"args,omitempty"`
	Env     json.RawMessage `json:"env,omitempty"`
	URL     string          `json:"url,omitempty"`
}

McpServer mirrors the editor-provided MCP server entry. ZERO owns its own MCP configuration (BYOK), so these are accepted for spec compliance; ZERO's configured servers remain authoritative.

type NewSessionParams

type NewSessionParams struct {
	Cwd                   string      `json:"cwd"`
	McpServers            []McpServer `json:"mcpServers"`
	AdditionalDirectories []string    `json:"additionalDirectories,omitempty"`
}

type NewSessionResult

type NewSessionResult struct {
	SessionID     string                `json:"sessionId"`
	ConfigOptions []SessionConfigOption `json:"configOptions,omitempty"`
	Modes         *SessionModeState     `json:"modes,omitempty"`
}

type NotifyFunc

type NotifyFunc func(ctx context.Context, params json.RawMessage)

NotifyFunc handles an inbound notification (no response is sent).

type PermissionOption

type PermissionOption struct {
	OptionID string `json:"optionId"`
	Name     string `json:"name"`
	Kind     string `json:"kind"`
}

type PlanEntry

type PlanEntry struct {
	Content  string `json:"content"`
	Priority string `json:"priority"`
	Status   string `json:"status"`
}

type PlanUpdate

type PlanUpdate struct {
	SessionUpdate string      `json:"sessionUpdate"`
	Entries       []PlanEntry `json:"entries"`
}

type PromptCapabilities

type PromptCapabilities struct {
	Image           bool `json:"image"`
	Audio           bool `json:"audio"`
	EmbeddedContext bool `json:"embeddedContext"`
}

type PromptParams

type PromptParams struct {
	SessionID string         `json:"sessionId"`
	Prompt    []ContentBlock `json:"prompt"`
}

type PromptResult

type PromptResult struct {
	StopReason string `json:"stopReason"`
}

type RequestPermissionOutcome

type RequestPermissionOutcome struct {
	Outcome  string `json:"outcome"`
	OptionID string `json:"optionId,omitempty"`
}

RequestPermissionOutcome is a tagged union: {"outcome":"cancelled"} or {"outcome":"selected","optionId":"..."}.

type RequestPermissionParams

type RequestPermissionParams struct {
	SessionID string             `json:"sessionId"`
	ToolCall  ToolCallUpdate     `json:"toolCall"`
	Options   []PermissionOption `json:"options"`
}

type RequestPermissionResult

type RequestPermissionResult struct {
	Outcome RequestPermissionOutcome `json:"outcome"`
}

type SessionConfigOption

type SessionConfigOption struct {
	ID          string                     `json:"id"`
	Name        string                     `json:"name"`
	Description string                     `json:"description,omitempty"`
	Value       string                     `json:"value"`
	Values      []SessionConfigOptionValue `json:"values,omitempty"`
}

type SessionConfigOptionValue

type SessionConfigOptionValue struct {
	ID   string `json:"id"`
	Name string `json:"name"`
}

type SessionMode

type SessionMode struct {
	ID          string `json:"id"`
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`
}

type SessionModeState

type SessionModeState struct {
	CurrentModeID  string        `json:"currentModeId"`
	AvailableModes []SessionMode `json:"availableModes"`
}

type SessionNotification

type SessionNotification struct {
	SessionID string `json:"sessionId"`
	Update    any    `json:"update"`
}

type SetSessionConfigOptionParams

type SetSessionConfigOptionParams struct {
	SessionID string `json:"sessionId"`
	ConfigID  string `json:"configId"`
	Value     string `json:"value"`
}

type SetSessionConfigOptionResult

type SetSessionConfigOptionResult struct {
	ConfigOptions []SessionConfigOption `json:"configOptions"`
}

type SetSessionModeParams

type SetSessionModeParams struct {
	SessionID string `json:"sessionId"`
	ModeID    string `json:"modeId"`
}

type SetSessionModeResult

type SetSessionModeResult struct{}

type ToolCallContent

type ToolCallContent struct {
	Type string `json:"type"`
	// type == "content"
	Content *ContentBlock `json:"content,omitempty"`
	// type == "diff"
	Path    string `json:"path,omitempty"`
	OldText string `json:"oldText,omitempty"`
	NewText string `json:"newText,omitempty"`
}

ToolCallContent is a tool call's rendered output. ZERO emits "content" (a text/image block) and "diff" (a file change); "terminal" is part of the spec but unused because ZERO executes locally.

func ToolContent

func ToolContent(block ContentBlock) ToolCallContent

func ToolDiff

func ToolDiff(path, oldText, newText string) ToolCallContent

type ToolCallLocation

type ToolCallLocation struct {
	Path string `json:"path"`
	Line *int   `json:"line,omitempty"`
}

type ToolCallUpdate

type ToolCallUpdate struct {
	SessionUpdate string             `json:"sessionUpdate,omitempty"`
	ToolCallID    string             `json:"toolCallId"`
	Title         string             `json:"title,omitempty"`
	Kind          string             `json:"kind,omitempty"`
	Status        string             `json:"status,omitempty"`
	RawInput      json.RawMessage    `json:"rawInput,omitempty"`
	Content       []ToolCallContent  `json:"content,omitempty"`
	Locations     []ToolCallLocation `json:"locations,omitempty"`
}

ToolCallUpdate is used for both the initial "tool_call" and subsequent "tool_call_update" notifications (distinguished by SessionUpdate). It also appears inside session/request_permission.

type ZeroSetModelParams

type ZeroSetModelParams struct {
	SessionID string `json:"sessionId"`
	Model     string `json:"model"`
}

type ZeroSetModelResult

type ZeroSetModelResult struct {
	Model string `json:"model"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL