hooks

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Sep 6, 2026 License: Apache-2.0 Imports: 5 Imported by: 0

Documentation

Overview

Package hooks gives a caller a named, multi-handler registry for a lifecycle point: Point, Handler, and a Registry whose Fire runs every handler at a point in registration order and stops at the first veto. A leaf package: no I/O, no goroutine, no persistence.

Map: point.go = Point, its named constants, Validate, and String; registry.go = Handler, Registry, New, Add, Remove, Fire, and the sentinel errors ErrBlankName, ErrNilHandler, ErrDuplicateName, ErrVetoed. Rationale: ../docs/plans/hooks.md. Contribution rules: ../AGENTS.md.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrBlankName is Add's error when name is empty after
	// strings.TrimSpace.
	ErrBlankName = errors.New("hooks: name must not be blank")
	// ErrNilHandler is Add's error for a nil Handler; a hook with
	// nothing to run has no purpose.
	ErrNilHandler = errors.New("hooks: handler must not be nil")
	// ErrDuplicateName is Add's error for a name already registered
	// at the same point. The same name may register at another point.
	ErrDuplicateName = errors.New("hooks: name already registered at point")
	// ErrVetoed is Fire's wrapped error when a handler returns false
	// with a nil error; test with errors.Is.
	ErrVetoed = errors.New("hooks: handler vetoed")
)

Sentinel errors for Registry operations; test with errors.Is.

Functions

This section is empty.

Types

type Handler

type Handler func(ctx context.Context, payload any) (bool, error)

Handler observes or vetoes one lifecycle point's action. payload is opaque to hooks: the caller that fires a point supplies whatever value that point's real action carries. Handler returns true, nil to allow the action to continue, false, nil to veto it, or a non-nil error when the handler itself failed to decide.

type Point

type Point int

Point names a lifecycle point a Registry groups handlers under.

const (

	// PointPreTool fires before a tool call runs.
	PointPreTool Point
	// PointPostTool fires once one tool call completes. The payload
	// type depends on the fire site: agentrun/wire.go sends the
	// confirmed envelope.Ack; agentloop/toolcall.go sends the
	// provider.ToolCall. Handlers must type-switch the payload.
	PointPostTool
	// PointStop fires at a run's stop.
	PointStop
)

func (Point) String

func (p Point) String() string

String returns a short label for each named constant, used in Fire's wrapped error messages. It returns "unknown" for an invalid value; it never panics.

func (Point) Validate

func (p Point) Validate() error

Validate rejects pointUnset and any value outside the three named constants.

type Registry

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

Registry holds named handlers grouped by Point, in registration order. Safe for concurrent Add, Remove, and Fire; a sync.Mutex guards the map. Build one with New.

func New

func New() *Registry

New creates an empty Registry.

func (*Registry) Add

func (r *Registry) Add(point Point, name string, h Handler) error

Add registers h under name at point. Rejects an invalid point with its Validate error, a blank name (empty after strings.TrimSpace) with ErrBlankName, a nil h with ErrNilHandler, and a name already registered at that same point with ErrDuplicateName. The same name may register at two different points; name scopes to one Point.

func (*Registry) Fire

func (r *Registry) Fire(ctx context.Context, point Point, payload any) error

Fire runs every handler registered at point, in registration order. An invalid point returns its Validate error at once, with no handler call. A point with no registered handlers returns nil at once. A handler returning true, nil moves Fire to the next handler. A handler returning false, nil stops Fire and returns ErrVetoed wrapped `hooks: %s: handler %q: %w`. A handler returning a non-nil error stops Fire and returns that error wrapped the same way. Fire returns nil once every handler has allowed. Fire releases the mutex before it calls a handler, so a slow handler never blocks a concurrent Add or Remove.

func (*Registry) Remove

func (r *Registry) Remove(point Point, name string) bool

Remove removes name from point. Returns whether the pair was present. Removing an absent name is not a fault; it returns false and changes nothing.

Jump to

Keyboard shortcuts

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