protocol

package
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Mar 2, 2026 License: GPL-3.0 Imports: 15 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)
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) 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) 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 added in v0.0.2

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