protocol

package
v0.0.13 Latest Latest
Warning

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

Go to latest
Published: Apr 23, 2026 License: GPL-3.0 Imports: 21 Imported by: 0

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, nil)
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

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.

func (*Controller) Start

func (c *Controller) Start(ctx context.Context) error

Start begins reading messages from the transport and routing control messages.

func (*Controller) Stop

func (c *Controller) Stop()

Stop gracefully shuts down the controller.

type RequestHandler

type RequestHandler func(ctx context.Context, req *ControlRequest) (map[string]any, error)

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

func NewSession(
	log *slog.Logger,
	controller *Controller,
	options *config.Options,
) *Session

NewSession creates a new Session for protocol handling.

func (*Session) GetInitializationResult

func (s *Session) GetInitializationResult() map[string]any

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

func (s *Session) GetSDKMCPServerNames() []string

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

func (s *Session) Initialize(ctx context.Context) error

Initialize sends the initialization control request to the CLI.

func (*Session) NeedsInitialization

func (s *Session) NeedsInitialization() bool

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.

type Transport

type Transport interface {
	ReadMessages(ctx context.Context) (<-chan map[string]any, <-chan error)
	SendMessage(ctx context.Context, data []byte) error
}

Transport defines the minimal interface needed for protocol operations.

Jump to

Keyboard shortcuts

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