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) HandleChatGPTAuthTokensRefresh(ctx context.Context, _ *ControlRequest) (map[string]any, error)
- func (s *Session) HandleDynamicToolCall(ctx context.Context, req *ControlRequest) (map[string]any, error)
- func (s *Session) HandleFileChangeApproval(ctx context.Context, req *ControlRequest) (map[string]any, error)
- func (s *Session) HandleMCPElicitation(ctx context.Context, req *ControlRequest) (map[string]any, error)
- func (s *Session) HandlePermissionsApproval(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) HandleChatGPTAuthTokensRefresh ¶ added in v0.0.7
func (s *Session) HandleChatGPTAuthTokensRefresh( ctx context.Context, _ *ControlRequest, ) (map[string]any, error)
HandleChatGPTAuthTokensRefresh handles account/chatgptAuthTokens/refresh requests used by app-server external-auth mode.
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) HandleFileChangeApproval ¶ added in v0.0.7
func (s *Session) HandleFileChangeApproval( ctx context.Context, req *ControlRequest, ) (map[string]any, error)
HandleFileChangeApproval handles item/fileChange/requestApproval requests. It routes through the CanUseTool callback if set, otherwise auto-accepts.
func (*Session) HandleMCPElicitation ¶ added in v0.0.7
func (s *Session) HandleMCPElicitation( ctx context.Context, req *ControlRequest, ) (map[string]any, error)
HandleMCPElicitation handles mcpServer/elicitation/request requests. It parses the request into typed elicitation types, invokes the OnElicitation callback, and serializes the response back to the wire format. If no callback is set, elicitation requests are auto-declined.
func (*Session) HandlePermissionsApproval ¶ added in v0.0.7
func (s *Session) HandlePermissionsApproval( ctx context.Context, req *ControlRequest, ) (map[string]any, error)
HandlePermissionsApproval handles item/permissions/requestApproval requests. It routes through the CanUseTool callback if set, otherwise auto-approves with the requested permissions scoped to the current turn.
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.