mail

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jan 22, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Overview

Package mail provides messaging for agent communication via beads.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrMessageNotFound = errors.New("message not found")
	ErrEmptyInbox      = errors.New("inbox is empty")
)

Common errors

View Source
var ErrUnknownAnnounce = errors.New("unknown announce channel")

ErrUnknownAnnounce indicates an announce channel name was not found in configuration.

View Source
var ErrUnknownList = errors.New("unknown mailing list")

ErrUnknownList indicates a mailing list name was not found in configuration.

View Source
var ErrUnknownQueue = errors.New("unknown queue")

ErrUnknownQueue indicates a queue name was not found in configuration.

Functions

func PriorityToBeads

func PriorityToBeads(p Priority) int

PriorityToBeads converts a GGT Priority to beads priority integer. Returns: 0=urgent, 1=high, 2=normal, 3=low

Types

type BeadsMessage

type BeadsMessage struct {
	ID          string    `json:"id"`
	Title       string    `json:"title"`       // Subject
	Description string    `json:"description"` // Body
	Assignee    string    `json:"assignee"`    // To identity
	Priority    int       `json:"priority"`    // 0=urgent, 1=high, 2=normal, 3=low
	Status      string    `json:"status"`      // open=unread, closed=read
	CreatedAt   time.Time `json:"created_at"`
	Labels      []string  `json:"labels"` // Metadata labels (from:X, thread:X, reply-to:X, msg-type:X, cc:X)
	Pinned      bool      `json:"pinned,omitempty"`
	Wisp        bool      `json:"wisp,omitempty"` // Ephemeral message (filtered from JSONL export)
	// contains filtered or unexported fields
}

BeadsMessage represents a message as returned by bd list/show commands. Messages are beads issues with type=message and metadata stored in labels.

func (*BeadsMessage) GetCC

func (bm *BeadsMessage) GetCC() []string

GetCC returns the parsed CC recipients.

func (*BeadsMessage) IsCCRecipient

func (bm *BeadsMessage) IsCCRecipient(identity string) bool

IsCCRecipient checks if the given identity is in the CC list.

func (*BeadsMessage) ParseLabels

func (bm *BeadsMessage) ParseLabels()

ParseLabels extracts metadata from the labels array.

func (*BeadsMessage) ToMessage

func (bm *BeadsMessage) ToMessage() *Message

ToMessage converts a BeadsMessage to a GGT Message.

type Delivery

type Delivery string

Delivery specifies how a message is delivered to the recipient.

const (
	// DeliveryQueue creates the message in the mailbox for periodic checking.
	// This is the default delivery mode. Agent checks with `gt mail check`.
	DeliveryQueue Delivery = "queue"

	// DeliveryInterrupt injects a system-reminder directly into the agent's session.
	// Use for lifecycle events, URGENT priority, or stuck detection.
	DeliveryInterrupt Delivery = "interrupt"
)

type GroupType

type GroupType string

GroupType represents the type of group address.

const (
	GroupTypeRig      GroupType = "rig"      // @rig/<rigname> - all agents in a rig
	GroupTypeTown     GroupType = "town"     // @town - all town-level agents
	GroupTypeRole     GroupType = "role"     // @witnesses, @dogs, etc. - all agents of a role
	GroupTypeRigRole  GroupType = "rig-role" // @crew/<rigname>, @polecats/<rigname> - role in a rig
	GroupTypeOverseer GroupType = "overseer" // @overseer - human operator
)

type Mailbox

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

Mailbox manages messages for an identity via beads.

func NewMailbox

func NewMailbox(path string) *Mailbox

NewMailbox creates a mailbox for the given JSONL path (legacy mode). Used by crew workers that have local JSONL inboxes.

func NewMailboxBeads

func NewMailboxBeads(identity, workDir string) *Mailbox

NewMailboxBeads creates a mailbox backed by beads.

func NewMailboxFromAddress

func NewMailboxFromAddress(address, workDir string) *Mailbox

NewMailboxFromAddress creates a beads-backed mailbox from a GGT address. Follows .beads/redirect for crew workers and polecats using shared beads.

func NewMailboxWithBeadsDir

func NewMailboxWithBeadsDir(address, workDir, beadsDir string) *Mailbox

NewMailboxWithBeadsDir creates a mailbox with an explicit beads directory.

func (*Mailbox) Append

func (m *Mailbox) Append(msg *Message) error

Append adds a message to the mailbox (legacy mode only). For beads mode, use Router.Send() instead.

func (*Mailbox) Archive

func (m *Mailbox) Archive(id string) error

Archive moves a message to the archive file and removes it from inbox.

func (*Mailbox) ArchivePath

func (m *Mailbox) ArchivePath() string

ArchivePath returns the path to the archive file.

func (*Mailbox) Count

func (m *Mailbox) Count() (total, unread int, err error)

Count returns the total and unread message counts.

func (*Mailbox) Delete

func (m *Mailbox) Delete(id string) error

Delete removes a message.

func (*Mailbox) Get

func (m *Mailbox) Get(id string) (*Message, error)

Get returns a message by ID.

func (*Mailbox) Identity

func (m *Mailbox) Identity() string

Identity returns the beads identity for this mailbox.

func (*Mailbox) List

func (m *Mailbox) List() ([]*Message, error)

List returns all open messages in the mailbox.

func (*Mailbox) ListArchived

func (m *Mailbox) ListArchived() ([]*Message, error)

ListArchived returns all messages in the archive file.

func (*Mailbox) ListByThread

func (m *Mailbox) ListByThread(threadID string) ([]*Message, error)

ListByThread returns all messages in a given thread.

func (*Mailbox) ListUnread

func (m *Mailbox) ListUnread() ([]*Message, error)

ListUnread returns unread (open) messages.

func (*Mailbox) MarkRead

func (m *Mailbox) MarkRead(id string) error

MarkRead marks a message as read.

func (*Mailbox) MarkUnread

func (m *Mailbox) MarkUnread(id string) error

MarkUnread marks a message as unread (reopens in beads).

func (*Mailbox) Path

func (m *Mailbox) Path() string

Path returns the JSONL path for legacy mailboxes.

func (*Mailbox) PurgeArchive

func (m *Mailbox) PurgeArchive(olderThanDays int) (int, error)

PurgeArchive removes messages from the archive, optionally filtering by age. If olderThanDays is 0, removes all archived messages.

func (*Mailbox) Search

func (m *Mailbox) Search(opts SearchOptions) ([]*Message, error)

Search finds messages matching the given criteria. Returns messages from both inbox and archive. Query and FromFilter are treated as literal strings (not regex) to prevent ReDoS.

type Message

type Message struct {
	// ID is a unique message identifier (beads issue ID like "bd-abc123").
	ID string `json:"id"`

	// From is the sender address (e.g., "gastown/Toast" or "mayor/").
	From string `json:"from"`

	// To is the recipient address.
	To string `json:"to"`

	// Subject is a brief summary.
	Subject string `json:"subject"`

	// Body is the full message content.
	Body string `json:"body"`

	// Timestamp is when the message was sent.
	Timestamp time.Time `json:"timestamp"`

	// Read indicates if the message has been read (closed in beads).
	Read bool `json:"read"`

	// Priority is the message priority.
	Priority Priority `json:"priority"`

	// Type indicates the message type (task, scavenge, notification, reply).
	Type MessageType `json:"type"`

	// Delivery specifies how the message is delivered (queue or interrupt).
	// Queue: agent checks periodically. Interrupt: inject into session.
	Delivery Delivery `json:"delivery,omitempty"`

	// ThreadID groups related messages into a conversation thread.
	ThreadID string `json:"thread_id,omitempty"`

	// ReplyTo is the ID of the message this is replying to.
	ReplyTo string `json:"reply_to,omitempty"`

	// Pinned marks the message as pinned (won't be auto-archived).
	Pinned bool `json:"pinned,omitempty"`

	// Wisp marks this as a transient message (stored in same DB but filtered from JSONL export).
	// Wisp messages auto-cleanup on patrol squash.
	Wisp bool `json:"wisp,omitempty"`

	// CC contains addresses that should receive a copy of this message.
	// CC'd recipients see the message in their inbox but are not the primary recipient.
	CC []string `json:"cc,omitempty"`
}

Message represents a mail message between agents. This is the GGT-side representation; it gets translated to/from beads messages.

func NewMessage

func NewMessage(from, to, subject, body string) *Message

NewMessage creates a new message with a generated ID and thread ID.

func NewReplyMessage

func NewReplyMessage(from, to, subject, body string, original *Message) *Message

NewReplyMessage creates a reply message that inherits the thread from the original.

type MessageType

type MessageType string

MessageType indicates the purpose of a message.

const (
	// TypeTask indicates a message requiring action from the recipient.
	TypeTask MessageType = "task"

	// TypeScavenge indicates optional first-come-first-served work.
	TypeScavenge MessageType = "scavenge"

	// TypeNotification is an informational message (default).
	TypeNotification MessageType = "notification"

	// TypeReply is a response to another message.
	TypeReply MessageType = "reply"
)

func ParseMessageType

func ParseMessageType(s string) MessageType

ParseMessageType parses a message type string, returning TypeNotification for invalid values.

type ParsedGroup

type ParsedGroup struct {
	Type     GroupType
	RoleType string // witness, crew, polecat, dog, etc.
	Rig      string // rig name for rig-scoped groups
	Original string // original @group string
}

ParsedGroup represents a parsed @group address.

type Priority

type Priority string

Priority levels for messages.

const (
	// PriorityLow is for non-urgent messages.
	PriorityLow Priority = "low"

	// PriorityNormal is the default priority.
	PriorityNormal Priority = "normal"

	// PriorityHigh indicates an important message.
	PriorityHigh Priority = "high"

	// PriorityUrgent indicates an urgent message requiring immediate attention.
	PriorityUrgent Priority = "urgent"
)

func ParsePriority

func ParsePriority(s string) Priority

ParsePriority parses a priority string, returning PriorityNormal for invalid values.

func PriorityFromInt

func PriorityFromInt(p int) Priority

PriorityFromInt converts a beads-style integer priority to a Priority. Accepts: 0=urgent, 1=high, 2=normal, 3=low, 4=backlog (treated as low). Invalid values default to PriorityNormal.

type Router

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

Router handles message delivery via beads. It routes messages to the correct beads database based on address: - Town-level (mayor/, deacon/) -> {townRoot}/.beads - Rig-level (rig/polecat) -> {townRoot}/{rig}/.beads

func NewRouter

func NewRouter(workDir string) *Router

NewRouter creates a new mail router. workDir should be a directory containing a .beads database. The town root is auto-detected from workDir if possible.

func NewRouterWithTownRoot

func NewRouterWithTownRoot(workDir, townRoot string) *Router

NewRouterWithTownRoot creates a router with an explicit town root.

func (*Router) ExpandListAddress

func (r *Router) ExpandListAddress(address string) ([]string, error)

ExpandListAddress expands a list:name address to its recipients. Returns ErrUnknownList if the list is not found. This is exported for use by commands that want to show fan-out details.

func (*Router) GetMailbox

func (r *Router) GetMailbox(address string) (*Mailbox, error)

GetMailbox returns a Mailbox for the given address. Routes to the correct beads database based on the address.

func (*Router) ResolveGroupAddress

func (r *Router) ResolveGroupAddress(address string) ([]string, error)

ResolveGroupAddress resolves a @group address to individual recipient addresses. Returns the list of resolved addresses and any error. This is the public entry point for group resolution.

func (*Router) Send

func (r *Router) Send(msg *Message) error

Send delivers a message via beads message. Routes the message to the correct beads database based on recipient address. Supports fan-out for: - Mailing lists (list:name) - fans out to all list members - @group addresses - resolves and fans out to matching agents Supports single-copy delivery for: - Queues (queue:name) - stores single message for worker claiming - Announces (announce:name) - bulletin board, no claiming, retention-limited

type SearchOptions

type SearchOptions struct {
	Query       string // Regex pattern to search for
	FromFilter  string // Optional: only match messages from this sender
	SubjectOnly bool   // Only search subject
	BodyOnly    bool   // Only search body
}

SearchOptions specifies search parameters.

Jump to

Keyboard shortcuts

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