events

package
v0.37.2 Latest Latest
Warning

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

Go to latest
Published: Sep 7, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package events is the wake-on-event inbox: external events (a mail reply, a CI failure) enter the server, are stored durably, and are either injected into the project's active session or wait in the inbox for the owner to decide. It owns the model and the store only; routing and injection live in pkg/serve.

Index

Constants

View Source
const (
	StateNew       = "new"
	StateRouting   = "routing"
	StateRouted    = "routed"
	StateDismissed = "dismissed"
)

Event states. An event has exactly one place: while `new` it is in the inbox, once `routed` it is the message in a session, and `dismissed` is the end of the line. There is no "read".

View Source
const (
	MaxSourceBytes  = 64
	MaxTitleBytes   = 200
	MaxBodyBytes    = 256 << 10
	MaxPayloadBytes = 64 << 10
	MaxKeyBytes     = 256
)

Field limits. The body as a whole is capped by the HTTP layer; a single oversized field is still harmful on its own (a 1 MiB title would pollute every inbox render).

View Source
const (
	PendingInbox              = "inbox"
	PendingNoSession          = "no_session"
	PendingManySessions       = "many_sessions"
	PendingSessionUnavailable = "session_unavailable"
	PendingSessionBusy        = "session_busy"
	PendingRateLimited        = "rate_limited"
)

PendingReason values. Stable API tokens; the client maps them to copy.

Variables

View Source
var ErrNotFound = errors.New("event not found")

ErrNotFound reports an unknown event id.

View Source
var ErrSettled = errors.New("event already settled")

ErrSettled reports an event that has already been routed or dismissed, so it cannot be acted on a second time (a double tap, or a retried request).

Functions

func NewID

func NewID() string

NewID mints an event identifier, using the same crypto/rand mechanism as core.NewMsgID.

Types

type Event

type Event struct {
	ID      string `json:"id"`
	Key     string `json:"key,omitempty"` // idempotency key, e.g. "agentmail:<message_id>"
	Source  string `json:"source"`        // "agentmail" | "ci" | free-form label
	Project string `json:"project"`       // canonical cwd
	Title   string `json:"title"`
	Body    string `json:"body,omitempty"`
	// Payload is opaque caller data. It is stored and returned but never
	// injected into a session: it is bookkeeping for the emitter, not something
	// an agent should be asked to read.
	Payload  json.RawMessage `json:"payload,omitempty"`
	Created  time.Time       `json:"created"`
	State    string          `json:"state"`
	RoutedTo string          `json:"routed_to,omitempty"`
	RoutedAt time.Time       `json:"routed_at,omitzero"`
	// Suggested is the session the inbox would send this event to, computed at
	// ingress so the card can name it. Empty when the project had no candidate.
	Suggested string `json:"suggested,omitempty"`
	// Autorun / Create* snapshot the source policy at ingest so a later config
	// change (or a deleted source) cannot start a turn the owner had not opted
	// into. Missing source → these stay at their zero values (autorun false).
	Autorun        bool   `json:"autorun,omitempty"`
	CreateModel    string `json:"create_model,omitempty"`
	CreateThinking string `json:"create_thinking,omitempty"`
	CreateYolo     bool   `json:"create_yolo,omitempty"`
	CreateTitle    string `json:"create_title,omitempty"`
	// PendingReason is why a `new` event is still in the inbox, set at the
	// routing decision so the row can say so without the owner guessing.
	PendingReason string `json:"pending_reason,omitempty"`
}

Event is one external notification addressed to a project (a canonical cwd).

type ParsedHook

type ParsedHook struct {
	Title string
	Body  string
	Key   string
}

ParsedHook is the title, body and idempotency key extracted from an arbitrary webhook payload.

func ParseHookBody

func ParseHookBody(source string, raw []byte) ParsedHook

ParseHookBody extracts a title, a body and a dedupe key from a hook payload. JSON objects look at title|subject|summary|event|message for a title and at id|event_id|key for a provider id; anything else is pretty-printed (or kept as text) and keyed by the SHA-256 of the raw bytes.

type Store

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

Store is a thread-safe, disk-backed inbox of events. Single-user personal use: one file, loaded at startup, rewritten atomically on every change.

func NewStore

func NewStore(path string) (*Store, error)

NewStore loads events from path (empty if the file does not exist yet).

func (*Store) Add

func (s *Store) Add(ev Event) (Event, bool, error)

Add stores an event and reports whether it was created now. An event whose (Source, Key) matches a stored one is NOT stored again: the existing event comes back with created=false, so a redelivered webhook neither injects a second message nor sends a second push.

func (*Store) DismissSource

func (s *Store) DismissSource(source string) (int, error)

DismissSource settles every pending event from source. Already routed or dismissed rows are left alone — history is not rewritten.

func (*Store) Get

func (s *Store) Get(id string) (Event, bool)

Get returns a stored event by id.

func (*Store) List

func (s *Store) List(state string) []Event

List returns the stored events in the given state, newest first. An empty state lists everything.

func (*Store) MarkDismissed

func (s *Store) MarkDismissed(id string) (Event, error)

MarkDismissed settles an event without sending it anywhere.

func (*Store) MarkRouted

func (s *Store) MarkRouted(id, sessionID string) (Event, error)

MarkRouted settles a claimed event onto a session. Only `routing` can become `routed`; a `new` event must be claimed first.

func (*Store) MarkRouting

func (s *Store) MarkRouting(id string) (Event, error)

MarkRouting CAS-claims a `new` event for delivery. A second claim (two concurrent route requests) reports ErrSettled so the message is injected at most once. Persist this transition before sending.

func (*Store) ReleaseRouting

func (s *Store) ReleaseRouting(id string) (Event, error)

ReleaseRouting returns a claimed event to `new` after a failed delivery.

func (*Store) SetPendingReason

func (s *Store) SetPendingReason(id, reason string) (Event, error)

SetPendingReason records why a `new` event stayed in the inbox. Settled events are left alone — the reason only applies while a decision is open.

func (*Store) SetSuggested

func (s *Store) SetSuggested(id, sessionID string) error

SetSuggested updates the session an inbox card offers to send to. Used when the suggestion is recomputed after ingress; a settled event is left alone.

Jump to

Keyboard shortcuts

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