Documentation
¶
Overview ¶
Package protocol implements bidirectional control message handling for the Codex CLI.
The protocol package provides a Controller that manages request/response correlation for control messages sent to and received from the Codex CLI. This enables interactive features like interruption, dynamic configuration changes, and hook callbacks.
The Controller handles:
- Sending control_request messages with unique IDs
- Receiving and correlating control_response messages
- Request timeout enforcement
- Handler registration for incoming requests from the CLI
Example usage:
transport := subprocess.NewCLITransport(log, "", options) transport.Start(ctx) controller := protocol.NewController(log, transport) controller.Start(ctx) // Send a request with timeout resp, err := controller.SendRequest(ctx, "interrupt", nil, 5*time.Second)
Index ¶
- type ControlRequest
- type ControlResponse
- type Controller
- func (c *Controller) Done() <-chan struct{}
- func (c *Controller) FatalError() error
- func (c *Controller) Messages() <-chan map[string]any
- func (c *Controller) RegisterHandler(subtype string, handler RequestHandler)
- func (c *Controller) SendRequest(ctx context.Context, subtype string, payload map[string]any, ...) (*ControlResponse, error)
- func (c *Controller) SetFatalError(err error)
- func (c *Controller) Start(ctx context.Context) error
- func (c *Controller) Stop()
- type RequestHandler
- type Session
- func (s *Session) GetInitializationResult() map[string]any
- func (s *Session) GetSDKMCPServer(name string) (mcp.ServerInstance, bool)
- func (s *Session) GetSDKMCPServerNames() []string
- func (s *Session) HandleCanUseTool(ctx context.Context, req *ControlRequest) (map[string]any, error)
- func (s *Session) HandleDynamicToolCall(ctx context.Context, req *ControlRequest) (map[string]any, error)
- func (s *Session) HandleRequestUserInput(ctx context.Context, req *ControlRequest) (map[string]any, error)
- func (s *Session) Initialize(ctx context.Context) error
- func (s *Session) NeedsInitialization() bool
- func (s *Session) RegisterDynamicTools()
- func (s *Session) RegisterHandlers()
- func (s *Session) RegisterMCPServers()
- type Transport
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ControlRequest ¶
type ControlRequest struct {
// Type is always "control_request"
Type string `json:"type"`
// RequestID uniquely identifies this request for response correlation
RequestID string `json:"request_id"` //nolint:tagliatelle // CLI uses snake_case
// Request contains the nested request data including subtype and payload fields
Request map[string]any `json:"request"`
}
ControlRequest represents a control message sent to or received from the CLI.
Wire format:
{
"type": "control_request",
"request_id": "req_1_abc123",
"request": {
"subtype": "initialize",
...
}
}
func (*ControlRequest) Subtype ¶
func (r *ControlRequest) Subtype() string
Subtype extracts the subtype from the nested request data.
type ControlResponse ¶
type ControlResponse struct {
// Type is always "control_response"
Type string `json:"type"`
// Response contains the nested response data
Response map[string]any `json:"response"`
}
ControlResponse represents a response to a control request.
Wire format for success:
{
"type": "control_response",
"response": {
"subtype": "success",
"request_id": "req_1_abc123",
"response": {...}
}
}
func (*ControlResponse) ErrorMessage ¶
func (r *ControlResponse) ErrorMessage() string
ErrorMessage extracts the error message from an error response.
func (*ControlResponse) IsError ¶
func (r *ControlResponse) IsError() bool
IsError checks if the response is an error response.
func (*ControlResponse) Payload ¶
func (r *ControlResponse) Payload() map[string]any
Payload extracts the response payload from a success response.
func (*ControlResponse) RequestID ¶
func (r *ControlResponse) RequestID() string
RequestID extracts the request_id from the nested response.
type Controller ¶
type Controller struct {
// contains filtered or unexported fields
}
Controller manages bidirectional control message communication with the CLI.
func NewController ¶
func NewController(log *slog.Logger, transport Transport) *Controller
NewController creates a new protocol controller.
func (*Controller) Done ¶
func (c *Controller) Done() <-chan struct{}
Done returns a channel that is closed when the controller stops.
func (*Controller) FatalError ¶
func (c *Controller) FatalError() error
FatalError returns the fatal error if one occurred.
func (*Controller) Messages ¶
func (c *Controller) Messages() <-chan map[string]any
Messages returns a channel for receiving non-control messages.
func (*Controller) RegisterHandler ¶
func (c *Controller) RegisterHandler(subtype string, handler RequestHandler)
RegisterHandler registers a handler for incoming control requests.
func (*Controller) SendRequest ¶
func (c *Controller) SendRequest( ctx context.Context, subtype string, payload map[string]any, timeout time.Duration, ) (*ControlResponse, error)
SendRequest sends a control request and waits for the response.
func (*Controller) SetFatalError ¶
func (c *Controller) SetFatalError(err error)
SetFatalError stores a fatal error and broadcasts to all waiters.
type RequestHandler ¶
RequestHandler is a function that handles incoming control requests from the CLI.
type Session ¶
type Session struct {
// contains filtered or unexported fields
}
Session encapsulates protocol handling logic for MCP servers and callbacks.
func NewSession ¶
NewSession creates a new Session for protocol handling.
func (*Session) GetInitializationResult ¶
GetInitializationResult returns a copy of the server initialization info.
func (*Session) GetSDKMCPServer ¶ added in v0.0.2
func (s *Session) GetSDKMCPServer(name string) (mcp.ServerInstance, bool)
GetSDKMCPServer returns a registered SDK MCP server by name.
func (*Session) GetSDKMCPServerNames ¶
GetSDKMCPServerNames returns the names of all registered SDK MCP servers.
func (*Session) HandleCanUseTool ¶
func (s *Session) HandleCanUseTool( ctx context.Context, req *ControlRequest, ) (map[string]any, error)
HandleCanUseTool is called by CLI before tool use.
func (*Session) HandleDynamicToolCall ¶
func (s *Session) HandleDynamicToolCall( ctx context.Context, req *ControlRequest, ) (map[string]any, error)
HandleDynamicToolCall handles item/tool/call requests from the CLI for SDK-registered dynamic tools and MCP server tools.
func (*Session) HandleRequestUserInput ¶
func (s *Session) HandleRequestUserInput( ctx context.Context, req *ControlRequest, ) (map[string]any, error)
HandleRequestUserInput handles item/tool/requestUserInput requests from the CLI. It parses the request into typed userinput types, invokes the OnUserInput callback, and serializes the response back to the wire format.
func (*Session) Initialize ¶
Initialize sends the initialization control request to the CLI.
func (*Session) NeedsInitialization ¶
NeedsInitialization returns true if the session has callbacks that require initialization.
func (*Session) RegisterDynamicTools ¶
func (s *Session) RegisterDynamicTools()
RegisterDynamicTools indexes SDK dynamic tools by name for dispatch.
func (*Session) RegisterHandlers ¶
func (s *Session) RegisterHandlers()
RegisterHandlers registers protocol handlers for MCP tool calls and command approval requests.
func (*Session) RegisterMCPServers ¶
func (s *Session) RegisterMCPServers()
RegisterMCPServers extracts and registers SDK MCP servers from options.