agent

package
v0.9.0 Latest Latest
Warning

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

Go to latest
Published: May 16, 2026 License: AGPL-3.0 Imports: 27 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// MidTaskPruneKeepStepsDefault is the number of recent tool-call steps to keep
	// intact when pruning older tool results during a multi-step agent run.
	MidTaskPruneKeepStepsDefault = 4
	// MidTaskPruneThresholdDefault is the minimum number of messages before pruning activates.
	MidTaskPruneThresholdDefault = 20
)
View Source
const (
	LoopDetectedAbortMessage        = "loop detected, stream aborted"
	LoopDetectedStreakThreshold     = 3
	LoopDetectedMinNewGramsPerChunk = 8
	LoopDetectedProbeChars          = 256
	ToolLoopDetectedAbortMessage    = "tool loop detected, stream aborted"
	ToolLoopRepeatThreshold         = 5
	ToolLoopWarningsBeforeAbort     = 1
	ToolLoopWarningKey              = "__memoh_tool_loop_warning" //nolint:gosec // internal warning key, not a credential
	ToolLoopWarningText             = ""                          //nolint:gosec // human-readable warning text, not a credential
	/* 196-byte string literal not displayed */

)

Loop detection constants matching the TypeScript implementation.

Variables

View Source
var (
	MemoryExtractPrompt string
	MemoryUpdatePrompt  string
)
View Source
var (
	ErrTextLoopDetected = errors.New(LoopDetectedAbortMessage)
	ErrToolLoopDetected = errors.New(ToolLoopDetectedAbortMessage)
)
View Source
var TimeNow = time.Now

TimeNow is a hook for testing. Defaults to time.Now.

Functions

func GenerateHeartbeatPrompt

func GenerateHeartbeatPrompt(interval int, checklist string, now time.Time, lastHeartbeatAt string) string

GenerateHeartbeatPrompt builds the user message for a heartbeat trigger.

func GenerateSchedulePrompt

func GenerateSchedulePrompt(s Schedule) string

GenerateSchedulePrompt builds the user message for a scheduled task trigger.

func GenerateSystemPrompt

func GenerateSystemPrompt(params SystemPromptParams) string

GenerateSystemPrompt builds the complete system prompt from files, skills, and context.

func SpawnModelCreatorFunc

func SpawnModelCreatorFunc() tools.ModelCreator

SpawnModelCreatorFunc returns a tools.ModelCreator backed by the shared SDK model factory. This keeps subagent model creation aligned with the shared SDK model factory.

func SpawnSystemPrompt

func SpawnSystemPrompt(sessionType string) string

SpawnSystemPrompt returns the system prompt for a given session type.

Types

type Agent

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

Agent is the core agent that handles LLM interactions.

func New

func New(deps Deps) *Agent

New creates a new Agent with the given dependencies.

func (*Agent) BridgeProvider

func (a *Agent) BridgeProvider() bridge.Provider

BridgeProvider returns the underlying bridge provider (workspace manager).

func (*Agent) ExecuteTool added in v0.8.0

func (a *Agent) ExecuteTool(ctx context.Context, cfg RunConfig, call sdk.ToolCall) (sdk.ToolResultPart, error)

func (*Agent) Generate

func (a *Agent) Generate(ctx context.Context, cfg RunConfig) (*GenerateResult, error)

Generate runs the agent in non-streaming mode, returning the complete result.

func (*Agent) SetToolProviders

func (a *Agent) SetToolProviders(providers []tools.ToolProvider)

SetToolProviders sets the tool providers after construction. This allows breaking dependency cycles in the DI graph.

func (*Agent) Stream

func (a *Agent) Stream(ctx context.Context, cfg RunConfig) <-chan StreamEvent

Stream runs the agent in streaming mode, emitting events to the returned channel.

type Deps

type Deps struct {
	BridgeProvider bridge.Provider
	Logger         *slog.Logger
}

Deps holds all service dependencies for the Agent.

type FSClient

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

FSClient provides file operations against a bot's container filesystem.

func NewFSClient

func NewFSClient(provider bridge.Provider, botID string, now func() time.Time) *FSClient

NewFSClient creates a new container filesystem client.

func (*FSClient) LoadSystemFiles

func (f *FSClient) LoadSystemFiles(ctx context.Context) []SystemFile

LoadSystemFiles loads the standard set of system files from the bot container.

func (*FSClient) ReadText

func (f *FSClient) ReadText(ctx context.Context, path string) (string, error)

ReadText reads a text file from the container, returning its content as a string. Returns an empty string if the file does not exist or cannot be read.

func (*FSClient) ReadTextSafe

func (f *FSClient) ReadTextSafe(ctx context.Context, path string) string

ReadTextSafe reads a text file, returning empty string on any error.

type FileAttachment

type FileAttachment struct {
	Type        string         `json:"type"`
	Base64      string         `json:"base64,omitempty"`
	Path        string         `json:"path,omitempty"`
	URL         string         `json:"url,omitempty"`
	PlatformKey string         `json:"platform_key,omitempty"`
	Mime        string         `json:"mime,omitempty"`
	Name        string         `json:"name,omitempty"`
	ContentHash string         `json:"content_hash,omitempty"`
	Size        int64          `json:"size,omitempty"`
	Metadata    map[string]any `json:"metadata,omitempty"`
}

FileAttachment represents a file reference extracted from agent output.

type GenerateResult

type GenerateResult struct {
	Messages    []sdk.Message
	Text        string
	Attachments []FileAttachment
	Reactions   []ReactionItem
	Speeches    []SpeechItem
	Usage       *sdk.Usage
}

GenerateResult holds the result of a non-streaming agent invocation.

type InjectMessage added in v0.7.0

type InjectMessage struct {
	Text            string
	HeaderifiedText string
	// ImageParts carries inline images (data URL or public URL) to attach
	// alongside the injected text when the model supports vision input.
	ImageParts []sdk.ImagePart
}

InjectMessage carries a user message to be injected into a running agent stream between tool rounds via the PrepareStep hook.

type LoopDetectionConfig

type LoopDetectionConfig struct {
	Enabled bool
}

LoopDetectionConfig controls loop detection behavior.

type ModelConfig

type ModelConfig struct {
	ModelID         string
	ClientType      string
	APIKey          string //nolint:gosec // carries provider credential material at runtime
	CodexAccountID  string
	BaseURL         string
	HTTPClient      *http.Client
	ReasoningConfig *ReasoningConfig
}

ModelConfig holds provider and model information resolved from DB.

type ReactionItem

type ReactionItem struct {
	Emoji string `json:"emoji"`
}

ReactionItem represents an emoji reaction extracted from agent output.

type ReasoningConfig

type ReasoningConfig struct {
	Enabled bool
	Effort  string
}

ReasoningConfig controls extended thinking/reasoning behavior.

type RetryConfig added in v0.7.0

type RetryConfig struct {
	MaxAttempts  int           // total retry attempts
	FastAttempts int           // first N attempts with no delay
	BaseDelay    time.Duration // backoff base for non-fast attempts
	MaxDelay     time.Duration // backoff cap
}

RetryConfig controls retry behavior for stream failures.

func DefaultRetryConfig added in v0.7.0

func DefaultRetryConfig() RetryConfig

DefaultRetryConfig returns the default retry strategy: 10 attempts total, first 5 fast (no delay), last 5 with exponential backoff.

type RunConfig

type RunConfig struct {
	Model              *sdk.Model
	ReasoningEffort    string
	Messages           []sdk.Message
	Query              string
	System             string
	SessionType        string
	SupportsImageInput bool
	SupportsToolCall   bool
	InlineImages       []sdk.ImagePart
	Identity           SessionContext
	Skills             []SkillEntry
	LoopDetection      LoopDetectionConfig
	Retry              RetryConfig

	// PromptCacheTTL controls prompt caching for this run. Empty or
	// unrecognized values default to 5m. Use "1h" for the long-cache tier
	// or "off" to disable caching entirely. The TTL is honored only when
	// the resolved model's vendor implements prompt caching (currently
	// Anthropic Messages); for other vendors the value is ignored.
	PromptCacheTTL string

	// MidTaskPruneThreshold is the minimum number of messages before mid-task
	// pruning kicks in. When the accumulated message count reaches this
	// threshold, older tool-result pairs are pruned to keep the context
	// within budget. Defaults to MidTaskPruneThresholdDefault (20).
	MidTaskPruneThreshold int

	// MidTaskPruneKeepSteps is the number of recent tool-call cycles to
	// preserve when mid-task pruning is triggered. Defaults to
	// MidTaskPruneKeepStepsDefault (4).
	MidTaskPruneKeepSteps int

	// InjectCh receives user messages to inject between tool rounds.
	// When non-nil, a PrepareStep hook drains this channel and appends
	// user messages to the conversation before the next LLM call.
	InjectCh <-chan InjectMessage

	// InjectedRecorder is called each time a message is injected via
	// PrepareStep, recording the headerified text and the number of SDK
	// output messages that preceded the injection. Used by the resolver
	// to interleave injected messages at the correct position in storeRound.
	InjectedRecorder func(headerifiedText string, insertAfter int)

	// BackgroundManager provides access to the background task system.
	// When non-nil, the agent loop drains pending notifications at step
	// boundaries and injects them as user messages so the model learns
	// about completed background work.
	BackgroundManager *background.Manager

	ToolApprovalHandler func(ctx context.Context, call sdk.ToolCall) (sdk.ToolApprovalResult, error)
}

RunConfig holds everything needed for a single agent invocation.

type Schedule

type Schedule struct {
	ID          string `json:"id"`
	Name        string `json:"name"`
	Description string `json:"description"`
	Pattern     string `json:"pattern"`
	MaxCalls    *int   `json:"maxCalls,omitempty"`
	Command     string `json:"command"`
}

Schedule represents a scheduled task definition.

type Sential

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

Sential detects text repetition via n-gram overlap.

func NewSential

func NewSential(opts SentialOptions) *Sential

NewSential creates a new n-gram overlap detector.

func (*Sential) Inspect

func (s *Sential) Inspect(text string) SentialResult

Inspect checks a chunk of text for n-gram overlap with the sliding window.

func (*Sential) Reset

func (s *Sential) Reset()

Reset clears the detector state.

type SentialOptions

type SentialOptions struct {
	NgramSize        int
	WindowSize       int
	OverlapThreshold float64
}

SentialOptions configures the n-gram overlap detector.

type SentialResult

type SentialResult struct {
	Hit          bool
	Overlap      float64
	MatchedGrams int
	NewGrams     int
}

SentialResult is the output of an overlap inspection.

type SessionContext

type SessionContext struct {
	BotID             string
	ChatID            string
	SessionID         string
	ChannelIdentityID string
	CurrentPlatform   string
	ReplyTarget       string
	ConversationType  string
	Timezone          string
	TimezoneLocation  *time.Location
	SessionToken      string //nolint:gosec // carries session credential material at runtime
	IsSubagent        bool
}

SessionContext carries request-scoped identity and routing information.

type SkillEntry

type SkillEntry struct {
	Name        string
	Description string
	Content     string
	Path        string
	Metadata    map[string]any
}

SkillEntry represents a skill loaded from the bot container.

type SpawnAdapter

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

SpawnAdapter wraps *Agent to satisfy tools.SpawnAgent without creating an import cycle (tools -> agent).

func NewSpawnAdapter

func NewSpawnAdapter(a *Agent) *SpawnAdapter

NewSpawnAdapter creates a SpawnAdapter from the given Agent.

func (*SpawnAdapter) Generate

func (*SpawnAdapter) GenerateWithWatchdog added in v0.7.0

func (s *SpawnAdapter) GenerateWithWatchdog(ctx context.Context, cfg tools.SpawnRunConfig, touchFn func()) (*tools.SpawnResult, error)

GenerateWithWatchdog runs the agent in streaming mode, touching the provided touchFn on every stream event (token, tool progress, etc.). It collects the full result and returns it in the same shape as Generate. This enables activity-based watchdog monitoring for subagent execution.

type SpeechItem

type SpeechItem struct {
	Text string `json:"text"`
}

SpeechItem represents a TTS request extracted from agent output.

type StreamEvent

type StreamEvent struct {
	Type           StreamEventType  `json:"type"`
	Delta          string           `json:"delta,omitempty"`
	ToolName       string           `json:"toolName,omitempty"`
	ToolCallID     string           `json:"toolCallId,omitempty"`
	ApprovalID     string           `json:"approvalId,omitempty"`
	ShortID        int              `json:"shortId,omitempty"`
	Status         string           `json:"status,omitempty"`
	Input          any              `json:"input,omitempty"`
	Metadata       map[string]any   `json:"metadata,omitempty"`
	Progress       any              `json:"progress,omitempty"`
	Result         any              `json:"result,omitempty"`
	Attachments    []FileAttachment `json:"attachments,omitempty"`
	Reactions      []ReactionItem   `json:"reactions,omitempty"`
	Speeches       []SpeechItem     `json:"speeches,omitempty"`
	Messages       json.RawMessage  `json:"messages,omitempty"`
	Usage          json.RawMessage  `json:"usage,omitempty"`
	Reasoning      []string         `json:"reasoning,omitempty"`
	Error          string           `json:"error,omitempty"`
	Attempt        int              `json:"attempt,omitempty"`
	MaxAttempt     int              `json:"maxAttempt,omitempty"`
	RetryError     string           `json:"retryError,omitempty"`
	StepNumber     int              `json:"stepNumber,omitempty"`
	TotalSteps     int              `json:"totalSteps,omitempty"`
	ProgressStatus string           `json:"progressStatus,omitempty"`
}

StreamEvent is emitted by the agent during streaming.

func (StreamEvent) IsTerminal

func (e StreamEvent) IsTerminal() bool

IsTerminal returns true for events that signal end of stream.

type StreamEventType

type StreamEventType string

StreamEventType identifies the kind of stream event.

const (
	EventAgentStart          StreamEventType = "agent_start"
	EventTextStart           StreamEventType = "text_start"
	EventTextDelta           StreamEventType = "text_delta"
	EventTextEnd             StreamEventType = "text_end"
	EventReasoningStart      StreamEventType = "reasoning_start"
	EventReasoningDelta      StreamEventType = "reasoning_delta"
	EventReasoningEnd        StreamEventType = "reasoning_end"
	EventToolCallStart       StreamEventType = "tool_call_start"
	EventToolCallProgress    StreamEventType = "tool_call_progress"
	EventToolCallEnd         StreamEventType = "tool_call_end"
	EventToolApprovalRequest StreamEventType = "tool_approval_request"
	EventAttachment          StreamEventType = "attachment_delta"
	EventReaction            StreamEventType = "reaction_delta"
	EventSpeech              StreamEventType = "speech_delta"
	EventAgentEnd            StreamEventType = "agent_end"
	EventAgentAbort          StreamEventType = "agent_abort"
	EventRetry               StreamEventType = "retry"
	EventProgress            StreamEventType = "progress"
	EventError               StreamEventType = "error"
)

type SystemFile

type SystemFile struct {
	Filename string
	Content  string
}

SystemFile is a file loaded from the bot container for prompt generation.

type SystemPromptParams

type SystemPromptParams struct {
	SessionType               string
	Skills                    []SkillEntry
	Files                     []SystemFile
	Now                       time.Time
	Timezone                  string
	SupportsImageInput        bool
	PlatformIdentitiesSection string
}

SystemPromptParams holds all inputs for system prompt generation.

type TextLoopGuard

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

TextLoopGuard wraps Sential with consecutive-hit tracking.

func NewTextLoopGuard

func NewTextLoopGuard(consecutiveHits, minNewGrams int, opts SentialOptions) *TextLoopGuard

NewTextLoopGuard creates a text loop guard.

func (*TextLoopGuard) Inspect

func (g *TextLoopGuard) Inspect(text string) TextLoopGuardResult

Inspect checks text and tracks consecutive overlap streaks.

func (*TextLoopGuard) Reset

func (g *TextLoopGuard) Reset()

Reset clears the guard state.

type TextLoopGuardResult

type TextLoopGuardResult struct {
	SentialResult
	Streak int
	Abort  bool
}

TextLoopGuardResult extends SentialResult with streak and abort tracking.

type TextLoopProbeBuffer

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

TextLoopProbeBuffer batches text into chunks before passing to an inspector.

func NewTextLoopProbeBuffer

func NewTextLoopProbeBuffer(chunkSize int, inspect func(string)) *TextLoopProbeBuffer

NewTextLoopProbeBuffer creates a probe buffer.

func (*TextLoopProbeBuffer) Flush

func (b *TextLoopProbeBuffer) Flush()

Flush emits any remaining content to the inspector.

func (*TextLoopProbeBuffer) Push

func (b *TextLoopProbeBuffer) Push(text string)

Push adds text to the buffer, emitting full chunks to the inspector.

type ToolLoopGuard

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

ToolLoopGuard detects repeated identical tool calls.

func NewToolLoopGuard

func NewToolLoopGuard(repeatThreshold, warningsBeforeAbort int) *ToolLoopGuard

NewToolLoopGuard creates a tool loop guard.

func (*ToolLoopGuard) Guard

func (g *ToolLoopGuard) Guard(toolName string, input any) (warn bool, abort bool)

Guard wraps tools with tool loop detection. Returns a wrapper execute function.

func (*ToolLoopGuard) Inspect

func (g *ToolLoopGuard) Inspect(input ToolLoopInput) ToolLoopResult

Inspect checks a tool call for repetition.

func (*ToolLoopGuard) Reset

func (g *ToolLoopGuard) Reset()

Reset clears the guard state.

type ToolLoopInput

type ToolLoopInput struct {
	ToolName string
	Input    any
}

ToolLoopInput represents a tool call for loop detection.

type ToolLoopResult

type ToolLoopResult struct {
	Hash        string
	RepeatCount int
	BreachCount int
	Warn        bool
	Abort       bool
}

ToolLoopResult is the output of a tool loop inspection.

Directories

Path Synopsis
Package background implements a background task manager for long-running commands executed inside bot containers.
Package background implements a background task manager for long-running commands executed inside bot containers.

Jump to

Keyboard shortcuts

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