injector

package
v0.0.0 Latest Latest
Warning

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

Go to latest
Published: Apr 9, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package injector provides the message injection system for synthetic conversation guidance.

Index

Constants

This section is empty.

Variables

AllTimings is the canonical ordered list of every Timing value.

Functions

This section is empty.

Types

type AfterResponseChecker

type AfterResponseChecker interface {
	CheckAfterResponse(ctx context.Context, state *State) *AfterResponseInjection
}

AfterResponseChecker is implemented by injectors that support AfterResponse timing.

type AfterResponseInjection

type AfterResponseInjection struct {
	Injection

	Response *sdk.ResponseModification
}

AfterResponseInjection is returned by AfterResponse hooks.

func (AfterResponseInjection) Base

func (inj AfterResponseInjection) Base() Injection

Base returns the embedded Injection.

type AfterToolChecker

type AfterToolChecker interface {
	CheckAfterTool(ctx context.Context, state *State) *AfterToolInjection
}

AfterToolChecker is implemented by injectors that support AfterToolExecution timing.

type AfterToolInjection

type AfterToolInjection struct {
	Injection

	Output *string
}

AfterToolInjection is returned by AfterToolExecution hooks.

func (AfterToolInjection) Base

func (inj AfterToolInjection) Base() Injection

Base returns the embedded Injection.

type AgentSwitchState

type AgentSwitchState struct {
	Previous string
	New      string
	Reason   string
}

AgentSwitchState holds agent switch event data.

type BeforeChatChecker

type BeforeChatChecker interface {
	CheckBeforeChat(ctx context.Context, state *State) *BeforeChatInjection
}

BeforeChatChecker is implemented by injectors that support BeforeChat timing.

type BeforeChatInjection

type BeforeChatInjection struct {
	Injection

	Request *sdk.RequestModification
}

BeforeChatInjection is returned by BeforeChat hooks.

func (BeforeChatInjection) Base

func (inj BeforeChatInjection) Base() Injection

Base returns the embedded Injection.

type BeforeCompactionChecker

type BeforeCompactionChecker interface {
	CheckBeforeCompaction(ctx context.Context, state *State) *BeforeCompactionInjection
}

BeforeCompactionChecker is implemented by injectors that support BeforeCompaction timing.

type BeforeCompactionInjection

type BeforeCompactionInjection struct {
	Injection

	Compaction *sdk.CompactionModification
}

BeforeCompactionInjection is returned by BeforeCompaction hooks.

func (BeforeCompactionInjection) Base

Base returns the embedded Injection.

type BeforeToolCheckItem

type BeforeToolCheckItem struct {
	Arguments map[string]any // if non-nil, replaces args for subsequent hooks
	Block     bool           // if true, skip tool execution
	Injection *Injection     // message to inject (nil = none)
}

BeforeToolCheckItem holds one hook's BeforeToolExecution result.

type BeforeToolCheckResult

type BeforeToolCheckResult struct {
	Arguments map[string]any // final args (chained through all hooks)
	Block     bool           // true if ANY hook blocked
	Messages  []Injection    // messages to inject
}

BeforeToolCheckResult holds the aggregated result of all BeforeToolExecution hooks.

type BeforeToolChecker

type BeforeToolChecker interface {
	CheckBeforeTool(
		ctx context.Context,
		state *State,
		toolName string,
		args map[string]any,
	) (*BeforeToolCheckItem, error)
}

BeforeToolChecker is implemented by injectors that support BeforeToolExecution timing. Defined here (not in plugins) to avoid an import cycle: registry type-asserts to this interface.

type CompactionState

type CompactionState struct {
	Enabled       bool
	Forced        bool // true if triggered by explicit /compact or force=true
	Success       bool
	PreMessages   int
	PostMessages  int
	SummaryLength int
	KeepLast      int // how many recent messages will be preserved
}

CompactionState holds compaction event data.

type Describer

type Describer interface {
	Describe() string
}

Describer is optionally implemented by injectors that provide extra display info.

type ErrorState

type ErrorState struct {
	Type      string // classified error type (e.g. "rate_limit", "network")
	Retryable bool   // true for transient errors
}

ErrorState holds classified error metadata.

type HasBase

type HasBase interface {
	Base() Injection
}

HasBase is implemented by typed injection structs to extract their base Injection.

type Injection

type Injection struct {
	Name        string // Injector name (e.g. "loop_detection", "max_steps")
	Role        roles.Role
	Content     string
	Prefix      string        // e.g., "[SYSTEM FEEDBACK]: "
	Eject       bool          // remove after one turn
	Tools       *config.Tools // tool filter for the turn this injection fires (nil = no override)
	DisplayOnly bool          // show in UI but don't add to conversation history
}

Injection represents the base message to inject. Timing-specific data lives in typed structs (BeforeChatInjection, AfterResponseInjection, etc.) that embed this.

func Bases

func Bases[T HasBase](items []T) []Injection

Bases extracts base Injection values from a typed injection slice. Go has no slice covariance, so this bridges typed slices to []Injection.

func (Injection) DisplayContent

func (inj Injection) DisplayContent() string

DisplayContent returns the injection content for UI display. Display-only injections are shown in full; conversation injections are truncated.

func (Injection) DisplayHeader

func (inj Injection) DisplayHeader() string

DisplayHeader returns the formatted header for UI display.

type Injector

type Injector interface {
	// Name returns a unique identifier for this injector.
	Name() string

	// Timing returns when this injector should run.
	Timing() Timing

	// Check determines if injection is needed given current state.
	// Returns nil if no injection needed.
	Check(ctx context.Context, state *State) *Injection

	// Enabled returns whether this injector is active.
	Enabled() bool
}

Injector produces messages to inject into the conversation.

type MessageTransformer

type MessageTransformer interface {
	TransformMessages(ctx context.Context, state *State, messages []sdk.Message) ([]sdk.Message, error)
}

MessageTransformer is implemented by injectors that support TransformMessages timing. Returns a modified message array for the current LLM call (ephemeral — builder history untouched).

type OnErrorChecker

type OnErrorChecker interface {
	CheckOnError(ctx context.Context, state *State) *OnErrorInjection
}

OnErrorChecker is implemented by injectors that support OnError timing.

type OnErrorInjection

type OnErrorInjection struct {
	Injection

	Error *sdk.ErrorModification
}

OnErrorInjection is returned by OnError hooks.

func (OnErrorInjection) Base

func (inj OnErrorInjection) Base() Injection

Base returns the embedded Injection.

type Registry

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

Registry manages registered injectors grouped by timing.

func New

func New() *Registry

New creates a new empty registry.

func (*Registry) Display

func (r *Registry) Display() string

Display returns a formatted listing of all registered injectors grouped by timing.

func (*Registry) FiredState

func (r *Registry) FiredState() map[string]bool

FiredState returns the names of injectors that have fired (once-per-session).

func (*Registry) HasTransformers

func (r *Registry) HasTransformers() bool

HasTransformers returns true if any enabled TransformMessages injectors are registered.

func (*Registry) Register

func (r *Registry) Register(i Injector)

Register adds an injector to the registry.

func (*Registry) RestoreFiredState

func (r *Registry) RestoreFiredState(state map[string]bool)

RestoreFiredState marks injectors as fired based on a previous snapshot.

func (*Registry) Run

func (r *Registry) Run(ctx context.Context, timing Timing, state *State) []Injection

Run executes all enabled injectors for a given timing. Returns all injections that triggered (may be empty).

func (*Registry) RunAfterResponse

func (r *Registry) RunAfterResponse(ctx context.Context, state *State) []AfterResponseInjection

RunAfterResponse runs all AfterResponse injectors and returns typed results.

func (*Registry) RunAfterTool

func (r *Registry) RunAfterTool(ctx context.Context, state *State) []AfterToolInjection

RunAfterTool runs all AfterToolExecution injectors and returns typed results.

func (*Registry) RunBeforeChat

func (r *Registry) RunBeforeChat(ctx context.Context, state *State) []BeforeChatInjection

RunBeforeChat runs all BeforeChat injectors and returns typed results.

func (*Registry) RunBeforeCompaction

func (r *Registry) RunBeforeCompaction(ctx context.Context, state *State) []BeforeCompactionInjection

RunBeforeCompaction runs all BeforeCompaction injectors and returns typed results.

func (*Registry) RunBeforeTool

func (r *Registry) RunBeforeTool(
	ctx context.Context,
	state *State,
	toolName string,
	args map[string]any,
) BeforeToolCheckResult

RunBeforeTool runs all BeforeToolExecution injectors with argument chaining. Each hook sees the modified args from the previous hook. Block is OR'd across all hooks.

func (*Registry) RunOnError

func (r *Registry) RunOnError(ctx context.Context, state *State) []OnErrorInjection

RunOnError runs all OnError injectors and returns typed results.

func (*Registry) RunTransformMessages

func (r *Registry) RunTransformMessages(ctx context.Context, state *State, messages []sdk.Message) []sdk.Message

RunTransformMessages runs all TransformMessages injectors as a pipeline. Each plugin's output feeds the next plugin's input. Errors are non-fatal — on error, the previous result is kept and the next plugin receives it.

type ResponseState

type ResponseState struct {
	Content      string     // response text content
	Thinking     string     // thinking block from this response
	Calls        []ToolCall // pending tool calls from this response (pre-execution)
	Empty        bool
	ContentEmpty bool
}

ResponseState holds the current response metadata.

type SandboxState

type SandboxState struct {
	Enabled   bool // Landlock actually enforcing
	Requested bool // User wants sandbox (may not be enforced)
}

SandboxState holds sandbox toggle state for plugin context.

type SessionState

type SessionState struct {
	ID    string
	Title string
}

SessionState holds session identity.

type State

type State struct {
	Iteration    int
	ToolHistory  []ToolCall
	Response     ResponseState
	HasToolCalls bool
	Todo         TodoState
	Mode         string
	Auto         bool
	PatchCounts  map[string]int
	Error        error
	ErrorInfo    ErrorState

	Tokens       TokenSnapshot
	MessageCount int

	// Value snapshots — frozen at build time, safe to read without mutation risk.
	Stats stats.Snapshot
	Model model.Model

	// Plugin SDK fields — used by plugin hooks to populate sdk.Context.
	Agent      string
	Workdir    string
	DoneActive bool
	MaxSteps   int

	Session         SessionState
	Provider        string
	ThinkMode       string
	Sandbox         SandboxState
	ReadBeforeWrite bool
	ShowThinking    bool
	Compaction      CompactionState

	AgentSwitch AgentSwitchState

	AvailableTools []string
	LoadedTools    []string
	Turns          []sdk.Turn
	SystemPrompt   string
	MCPServers     []string
	Vars           map[string]string
}

State provides context about the current conversation state.

func (*State) ConditionState

func (s *State) ConditionState() condition.State

ConditionState converts the injector state to a condition evaluation state.

func (*State) LastTool

func (s *State) LastTool() *ToolCall

LastTool returns the most recent tool call, or nil if none.

func (*State) PrevTool

func (s *State) PrevTool() *ToolCall

PrevTool returns the second-to-last tool call, or nil if none.

type Stateful

type Stateful interface {
	HasFired() bool
	MarkFired(bool)
}

Stateful is optionally implemented by injectors that track once-per-session state. Used to preserve fired state across config reloads.

type Timing

type Timing int

Timing defines when an injector runs.

const (
	// BeforeChat runs before sending to LLM.
	BeforeChat Timing = iota
	// AfterResponse runs after receiving LLM response.
	AfterResponse
	// BeforeToolExecution runs before each tool execution.
	BeforeToolExecution
	// AfterToolExecution runs after each tool execution.
	AfterToolExecution
	// OnError runs when an error occurs.
	OnError
	// AfterCompaction runs after context compaction completes.
	AfterCompaction
	// OnAgentSwitch runs when the active agent changes.
	OnAgentSwitch
	// BeforeCompaction runs before context compaction begins.
	BeforeCompaction
	// TransformMessages runs inside chat() to transform the message array before the LLM call.
	TransformMessages
)

func (Timing) String

func (t Timing) String() string

String returns the human-readable name of a Timing value.

type TodoState

type TodoState struct {
	Pending    int
	InProgress int
	Total      int
}

TodoState holds todo list counts.

type TokenSnapshot

type TokenSnapshot struct {
	Estimate int     // Client-side estimate: per-message sum + tool schema tokens (forward-looking)
	LastAPI  int     // API-reported input tokens from last provider chat() call (backward-looking)
	Percent  float64 // 0-100 range, based on Estimate
	Max      int     // Effective context window size in tokens
}

TokenSnapshot holds token measurements frozen at state build time.

type ToolCall

type ToolCall struct {
	Name     string
	Args     map[string]any
	Result   string
	Error    string
	Duration time.Duration
}

ToolCall captures a single tool invocation.

Jump to

Keyboard shortcuts

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