triggers

package
v1.187.0 Latest Latest
Warning

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

Go to latest
Published: Aug 16, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

* ChatCLI - MCP channel reactive triggers * Copyright (c) 2024 Edilson Freitas * License: Apache-2.0 * * The trigger engine turns inbound MCP channel messages into actionable * events for the CLI. Three modes are supported: * * notify — show a discreet banner above the next prompt and bump * the unread counter. Default mode. Zero side effects. * confirm — same banner, plus a one-line yes/no prompt the user * resolves manually (via /channel confirm <id> [yes|no]). * auto — when the session is idle, schedule the configured prompt * to run as a synthetic agent turn, rendered inside a * clearly-marked auto-run envelope. Tool whitelist and * rate-limit per rule enforce guard-rails. * * This package is intentionally agnostic of the CLI UI: the engine * emits a stream of Action values; the CLI subscribes and decides * how/where to render and how to gate on session state. * * Concurrency: the engine is safe for concurrent rule reloads and * concurrent Dispatch calls. Per-rule rate-limit state lives in * sync.Map so adding/removing rules at runtime never invalidates * other rules' state.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Action

type Action struct {
	ID         uint64
	Rule       Rule
	Event      ChannelEvent
	Mode       Mode
	Prompt     string // already-rendered template, ready to feed the agent
	IssuedAt   time.Time
	ExpiresAt  time.Time // for confirm actions; zero means no expiration
	ToolFilter []string  // copy of Rule.Tools so consumers do not race
}

Action is what the engine emits when a rule fires. The CLI listens on Engine.Actions() and decides UI behavior per mode.

ID is unique per emitted Action (not per Rule) — the CLI uses it to address pending confirm actions when the user responds with /channel confirm <id>.

type ChannelEvent

type ChannelEvent struct {
	ServerName string
	Channel    string
	Content    string
	Metadata   map[string]string
	Timestamp  time.Time
	Seq        uint64
}

ChannelEvent is the trigger engine's view of an incoming MCP message. Decoupled from cli/mcp.ChannelMessage so the engine has no import dependency back into the manager — keeps the package boundary clean.

type Engine

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

Engine evaluates rules against incoming events and dispatches actions on a buffered channel for downstream UI/agent consumers.

Lifecycle:

e := triggers.NewEngine(logger)
e.SetRules(initial)        // safe to call again on /config reload
e.Dispatch(event)          // wired to ChannelManager.OnMessage
for a := range e.Actions() { ... }
e.Close()                  // drains and closes the actions chan

func NewEngine

func NewEngine(logger *zap.Logger) *Engine

NewEngine constructs an engine with default options.

func NewEngineWithOptions

func NewEngineWithOptions(logger *zap.Logger, opts EngineOptions) *Engine

NewEngineWithOptions constructs an engine with explicit options.

func (*Engine) Actions

func (e *Engine) Actions() <-chan Action

Actions exposes the read end of the action stream. Consumers MUST keep up — when the channel fills, the engine logs a warning and drops the newest action. (Confirm/Auto actions are not retried; the next matching event will produce a fresh Action.)

func (*Engine) Close

func (e *Engine) Close()

Close drains and closes the actions channel. Idempotent — safe to call from the CLI shutdown path even if the engine was never started.

func (*Engine) Dispatch

func (e *Engine) Dispatch(event ChannelEvent)

Dispatch runs each rule against the event and emits an Action for every match (subject to rate-limit and dedup). Safe to call from multiple goroutines — typically wired directly to ChannelManager.OnMessage.

func (*Engine) IsPaused

func (e *Engine) IsPaused() bool

IsPaused reports whether the engine is currently suspended.

func (*Engine) Pause

func (e *Engine) Pause()

Pause suspends all trigger evaluation until Resume is called. Dispatch keeps draining events so the channel never blocks, but no Actions are emitted while paused.

func (*Engine) Resume

func (e *Engine) Resume()

func (*Engine) Rules

func (e *Engine) Rules() []Rule

Rules returns a snapshot of the active rule set. Useful for /channel rules introspection.

func (*Engine) SetRules

func (e *Engine) SetRules(rules []Rule) error

SetRules replaces the active rule set atomically. Returns the first validation error encountered, with no partial application — either every rule is accepted or none are.

Safe to call concurrently with Dispatch. The next Dispatch picks up the new rules; in-flight ones continue with the snapshot they captured at entry.

type EngineOptions

type EngineOptions struct {
	// ActionBuffer caps how many pending actions can be queued before
	// Dispatch starts dropping the oldest. Zero → 64, which is more
	// than enough for the bursty CI/Prometheus use case.
	ActionBuffer int
}

EngineOptions configures the engine. All fields optional.

type Mode

type Mode string

Mode declares how the CLI should surface a fired trigger to the user.

const (
	// ModeNotify — banner only. Default and safest.
	ModeNotify Mode = "notify"
	// ModeConfirm — banner plus an explicit user yes/no.
	ModeConfirm Mode = "confirm"
	// ModeAuto — fully autonomous when session is idle.
	ModeAuto Mode = "auto"
)

func (Mode) IsValid

func (m Mode) IsValid() bool

IsValid reports whether m is one of the three supported modes. Used by config validation so a typo in the rules file becomes a startup-time error rather than a silent fallback.

type Rule

type Rule struct {
	Name         string        `json:"name"`
	Server       string        `json:"server,omitempty"`
	Channel      string        `json:"channel,omitempty"`
	ContentRegex string        `json:"contentRegex,omitempty"`
	Mode         Mode          `json:"mode,omitempty"`
	Prompt       string        `json:"prompt,omitempty"`
	Tools        []string      `json:"tools,omitempty"`
	RateLimit    time.Duration `json:"-"` // populated from RateLimitText
	RateLimitTxt string        `json:"rateLimit,omitempty"`
	DedupWindow  time.Duration `json:"-"`
	DedupTxt     string        `json:"dedupWindow,omitempty"`
	// contains filtered or unexported fields
}

Rule declares how a single trigger reacts to incoming events.

Match semantics: an empty Server / Channel / ContentRegex matches everything. When multiple fields are specified, all must match (AND). When a Rule produces a fire, its Prompt template is rendered against the matched ChannelEvent.

Tools is the optional whitelist of MCP/native tool names the auto-run session may invoke. Empty list means "no restriction" for backward-compatible behavior in notify/confirm modes; in auto mode an empty list is rejected by Validate because running the agent without a tool floor is a foot-gun.

Jump to

Keyboard shortcuts

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