control

package
v0.28.0 Latest Latest
Warning

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

Go to latest
Published: Aug 8, 2026 License: MIT Imports: 21 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrRuntimeNotFound = errors.New("runtime not found")

Functions

This section is empty.

Types

type ControlServer

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

func NewServer

func NewServer(state *ControlState) *ControlServer

func (*ControlServer) AnswerPendingPermission

func (s *ControlServer) AnswerPendingPermission(scope, requestID, optionID, message string) bool

AnswerPendingPermission accepts an answer for the active permission claim. An already-resolved claim is also accepted as a benign no-op.

func (*ControlServer) BeginPermissionClaim

func (s *ControlServer) BeginPermissionClaim(scope, requestID string) (<-chan PermissionAnswer, <-chan struct{}, bool)

BeginPermissionClaim registers a permission claim within scope and returns its answer channel and a disconnect channel. The disconnect channel is closed when all control-socket clients disconnect while the claim is in the Reserved or Control state, allowing the resolver to fall through to a fallback handler. Request IDs are only unique within an ACP session, so stable runtimes must use distinct scopes.

func (*ControlServer) CanonicalizeEvent

func (s *ControlServer) CanonicalizeEvent(event events.Event) events.Event

func (*ControlServer) ClearPermissionClaims

func (s *ControlServer) ClearPermissionClaims(scope string)

func (*ControlServer) ConsumeInterrupt

func (s *ControlServer) ConsumeInterrupt() string

func (*ControlServer) DeliverPendingPermission

func (s *ControlServer) DeliverPendingPermission(scope, requestID, optionID, message string) PermissionAnswerDelivery

DeliverPendingPermission distinguishes a missing claim from a claim that has already resolved. It checks claim.state before validating payloads. For PermissionResolverResolved, it returns AlreadyResolved without a provider.

func (*ControlServer) DequeuePrompt

func (s *ControlServer) DequeuePrompt() string

func (*ControlServer) EndPermissionClaim

func (s *ControlServer) EndPermissionClaim(scope, requestID string)

func (*ControlServer) HandoffPermissionClaim

func (s *ControlServer) HandoffPermissionClaim(scope, requestID string, next PermissionResolverState) (PermissionAnswer, bool)

HandoffPermissionClaim atomically consumes an answer already queued for the control resolver or closes control ownership by transitioning to next. Once it returns without an answer, later control deliveries are rejected.

func (*ControlServer) HasClients

func (s *ControlServer) HasClients() bool

HasClients reports whether the control plane has at least one connected client capable of answering control RPCs. Returns false when no socket is bound (e.g. --http-debug without --control-socket) or when no client has dialed in yet. Used to gate features that should defer to fallbacks (file-handler permissions) when nothing on the socket can answer.

func (*ControlServer) HasPendingPermission

func (s *ControlServer) HasPendingPermission() bool

HasPendingPermission reports whether a permission claim is currently registered. Used by tests to verify claims are cleaned up after timeout.

func (*ControlServer) InterruptChan

func (s *ControlServer) InterruptChan() <-chan struct{}

InterruptChan returns the channel that closes when an interrupt fires. Idempotent: returns the same channel until ResetInterrupt is called.

func (*ControlServer) InterruptPrompt

func (s *ControlServer) InterruptPrompt(text string, keepQueue bool)

func (*ControlServer) MarkPermissionClaimResolved

func (s *ControlServer) MarkPermissionClaimResolved(scope, requestID, source string) bool

MarkPermissionClaimResolved changes claim.state to PermissionResolverResolved. DeliverPendingPermission returns AlreadyResolved for that state. Live-only channels and queued metadata are cleared so the resolved claim cannot be mistaken for a pending request. Channels are safely closed to unblock any lingering waiters before being set to nil.

func (*ControlServer) PermissionResolverState

func (s *ControlServer) PermissionResolverState(scope, requestID string) PermissionResolverState

func (*ControlServer) PreparePermissionClaim

func (s *ControlServer) PreparePermissionClaim(scope, requestID string, state PermissionResolverState, options []any) bool

PreparePermissionClaim records resolver ownership before permission.request is published. Terminal entries may be replaced when an ACP session reuses a request ID for a later request.

func (*ControlServer) PreparePermissionClaimAfterDirectDelivery

func (s *ControlServer) PreparePermissionClaimAfterDirectDelivery(ctx context.Context, scope, requestID string, state PermissionResolverState, options []any) bool

PreparePermissionClaimAfterDirectDelivery serializes request-ID reuse with a direct provider answer already in flight. It never holds pendingMu while it waits, so provider completion can take the normal writeMu -> controlMu -> pendingMu path before the replacement claim is prepared.

func (*ControlServer) PreparePermissionClaimAfterDirectDeliveryWith

func (s *ControlServer) PreparePermissionClaimAfterDirectDeliveryWith(ctx context.Context, scope, requestID string, state PermissionResolverState, options []any, onPrepared func()) bool

PreparePermissionClaimAfterDirectDeliveryWith invokes onPrepared while the new claim is still protected by the server and pending-claim locks. The callback must not call ControlServer methods; stable runtimes use it only to publish an exact provider-generation binding before the claim is answerable.

func (*ControlServer) PublishCanonicalEvent

func (s *ControlServer) PublishCanonicalEvent(event events.Event)

func (*ControlServer) PublishEvent

func (s *ControlServer) PublishEvent(event events.Event) events.Event

func (*ControlServer) QueuePrompt

func (s *ControlServer) QueuePrompt(text string)

func (*ControlServer) ResetInterrupt

func (s *ControlServer) ResetInterrupt()

ResetInterrupt closes the current interrupt channel (if any) and creates a fresh one. Call this between turns to re-arm the interrupt signal.

func (*ControlServer) RetryDirectPermissionDelivery

func (s *ControlServer) RetryDirectPermissionDelivery(scope, requestID string) bool

RetryDirectPermissionDelivery returns a failed direct delivery to the unowned state. It only changes the exact in-flight claim, so cleanup or a replacement claim cannot be overwritten by a late failure.

func (*ControlServer) SetCancelFunc

func (s *ControlServer) SetCancelFunc(fn func())

func (*ControlServer) SetPermissionResolverState

func (s *ControlServer) SetPermissionResolverState(scope, requestID string, state PermissionResolverState)

func (*ControlServer) SetStableHandler

func (s *ControlServer) SetStableHandler(h StableHandler)

func (*ControlServer) Start

func (s *ControlServer) Start(socketPath string) error

func (*ControlServer) Stop

func (s *ControlServer) Stop()

func (*ControlServer) SubscribeEvents

func (s *ControlServer) SubscribeEvents(ctx context.Context) <-chan events.Event

type ControlState

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

func NewState

func NewState(runID, runLabel string, maxRetries int) *ControlState

func (*ControlState) FinalOutput

func (s *ControlState) FinalOutput() string

FinalOutput returns the complete terminal reply retained for avenor_result. It is deliberately not part of Snapshot's JSON status representation.

func (*ControlState) Snapshot

func (s *ControlState) Snapshot() Snapshot

func (*ControlState) Update

func (s *ControlState) Update(fn func(*Snapshot))

type HTTPDebugServer

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

func NewHTTPDebugServer

func NewHTTPDebugServer(addr string, control *ControlServer) (*HTTPDebugServer, error)

func (*HTTPDebugServer) SetStableAdapter

func (h *HTTPDebugServer) SetStableAdapter(a StableAdapter)

SetStableAdapter wires a StableAdapter into the debug server so that per-runtime endpoints are active. The supervisor calls this immediately after NewHTTPDebugServer; CLI mode never calls it. Passing nil is a no-op.

func (*HTTPDebugServer) Start

func (h *HTTPDebugServer) Start() error

func (*HTTPDebugServer) Stop

func (h *HTTPDebugServer) Stop(ctx context.Context) error

type Notification

type Notification struct {
	JSONRPC string `json:"jsonrpc"`
	Method  string `json:"method"`
	Params  any    `json:"params,omitempty"`
}

type PermissionAnswer

type PermissionAnswer struct {
	RequestID string `json:"request_id"`
	OptionID  string `json:"option_id"`
	Message   string `json:"message,omitempty"`
}

func (*PermissionAnswer) UnmarshalJSON

func (p *PermissionAnswer) UnmarshalJSON(data []byte) error

type PermissionAnswerDelivery

type PermissionAnswerDelivery uint8
const (
	PermissionAnswerNotFound PermissionAnswerDelivery = iota
	PermissionAnswerDelivered
	PermissionAnswerAlreadyResolved
	PermissionAnswerChannelFull
	PermissionAnswerResolverOwned
	PermissionAnswerNoResolver
	PermissionAnswerInvalid
)

type PermissionResolverState

type PermissionResolverState uint8
const (
	PermissionResolverUnknown PermissionResolverState = iota
	PermissionResolverReserved
	PermissionResolverControl
	PermissionResolverAutomatic
	PermissionResolverFile
	PermissionResolverNoResolver
	PermissionResolverDirectDelivery
	PermissionResolverResolved
)

func (PermissionResolverState) String

func (s PermissionResolverState) String() string

type Request

type Request struct {
	JSONRPC string          `json:"jsonrpc"`
	ID      any             `json:"id,omitempty"`
	Method  string          `json:"method"`
	Params  json.RawMessage `json:"params,omitempty"`
}

type RespError

type RespError struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
	Data    any    `json:"data,omitempty"`
}

type Response

type Response struct {
	JSONRPC string     `json:"jsonrpc"`
	ID      any        `json:"id"`
	Result  any        `json:"result,omitempty"`
	Error   *RespError `json:"error,omitempty"`
}

type Snapshot

type Snapshot struct {
	SessionID         string         `json:"session_id,omitempty"`
	RunID             string         `json:"run_id,omitempty"`
	RunLabel          string         `json:"run_label,omitempty"`
	Phase             string         `json:"phase,omitempty"`
	PhaseLabel        string         `json:"phase_label,omitempty"`
	LastEvent         string         `json:"last_event,omitempty"`
	RetryAttempt      int            `json:"retry_attempt,omitempty"`
	MaxRetries        int            `json:"max_retries,omitempty"`
	PendingPermission bool           `json:"pending_permission"`
	Permission        map[string]any `json:"permission,omitempty"`
	StartedAt         int64          `json:"started_at"`
	UpdatedAt         int64          `json:"updated_at"`
	TurnState         string         `json:"turn_state,omitempty"`
	LatestSeq         int64          `json:"latest_seq,omitempty"`
	// FinalOutput is a bounded status preview. The complete terminal reply is
	// retained separately for the explicit result control method.
	FinalOutput          string `json:"final_output,omitempty"`
	FinalOutputTruncated bool   `json:"final_output_truncated,omitempty"`
	FullFinalOutput      string `json:"-"`
}

type StableAdapter

type StableAdapter interface {
	// HTTPRuntimeStatus returns the runtime snapshot for the given runtimeID.
	// Returns ErrRuntimeNotFound if the runtime ID does not exist.  Other
	// errors indicate operational failures and should map to 500.
	HTTPRuntimeStatus(runtimeID string) (any, error)
	// HTTPCancelRuntime cancels the named runtime.  Returns ErrRuntimeNotFound
	// if the runtime ID does not exist.  Other errors indicate operational
	// failures and should map to 500.
	HTTPCancelRuntime(runtimeID string) error
}

StableAdapter is the minimal interface that HTTPDebugServer needs to serve per-runtime endpoints in stable mode. The supervisor implements this; CLI mode passes nil (no adapter wired).

Method names are prefixed with HTTP to avoid shadowing the StableHandler methods on *Supervisor which carry the same logical names but different signatures (e.g. RuntimeStatus returns (any, error) there).

type StableHandler

type StableHandler interface {
	Spawn(params json.RawMessage) (any, error)
	List() any
	Shutdown(mode string) error
	RuntimeStatus(runtimeID string) (any, error)
	RuntimeCancel(runtimeID string) error
	RuntimePrompt(runtimeID, text, requestID string) error
	RuntimeAnswerPermission(runtimeID, requestID, optionID, message string) error
	RuntimeInterruptAndPrompt(runtimeID, text string, keepQueue bool) error
	RuntimeSendToParent(runtimeID, message string) error

	// TreeBudgetStatus reports tree-budget diagnostics. A supervisor without an
	// active budget returns a degraded status map with its reason.
	TreeBudgetStatus() any

	// WaitForCapacityMS blocks until a tree budget slot may be available or the
	// given timeout (milliseconds) elapses. Returns nil when capacity may be
	// available, or an error on timeout/shutdown. It does not reserve capacity.
	WaitForCapacityMS(timeoutMS int) error
}

Jump to

Keyboard shortcuts

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