state

package
v0.13.0 Latest Latest
Warning

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

Go to latest
Published: Aug 14, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package state is the gateway's durable bookkeeping — the state that MUST survive a restart for the gateway to behave correctly: a durable INBOX of accepted-but-not-yet-processed messages (so a message is never lost between being acked to the provider and being run), and each polling channel's ack cursor (so a restart resumes where it left off). Both Hermes and OpenClaw's worst, money-losing bugs trace to keeping this state in memory; we keep it in a dedicated SQLite file, separate from the core event store.

The inbox row's (channel, message_id) primary key also serves as the dedup key: a redelivery inserts nothing (fresh=false) and is dropped.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Item

type Item struct {
	Channel      string
	MessageID    string
	Conversation string
	Principal    string
	Text         string
	Trusted      bool
	Reply        string
	Agent        string // persona snapshot at receipt
	Project      string // project id snapshot at receipt
}

Item is one inbound message durably recorded for processing. Reply is set only for items returned by PendingReplies (the job finished; the reply awaits delivery).

type Store

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

Store is the gateway's durable state.

func Open

func Open(ctx context.Context, dir string) (*Store, error)

Open opens (creating if needed) the gateway state DB at dir/gateway.db. It also takes an exclusive lock on the project so a second `memcode gateway` for the same repo cannot start and double-process the shared inbox — the in-memory dedup guard only protects a single process. The lock releases when the Store is closed or the process exits.

func (*Store) Accept

func (s *Store) Accept(ctx context.Context, it Item, now time.Time) (bool, error)

Accept durably records an inbound message as pending and reports whether this call is the one that recorded it. fresh=true means "you own this message, ack the provider and it will be processed"; fresh=false means it was already seen (a duplicate delivery or a concurrent racer) and must be dropped. The insert is atomic, so it also guards two concurrent deliveries of the same id. Callers ack the provider only after Accept returns without error, so a crash before the durable write re-delivers rather than loses the message.

func (*Store) Close

func (s *Store) Close() error

Close closes the database and releases the project lock.

func (*Store) Conversation added in v0.13.0

func (s *Store) Conversation(ctx context.Context, channel, conversation string) (agent, project string, err error)

Conversation returns the persona and project this conversation currently points at (empty when unset — the caller applies channel/gateway defaults).

func (*Store) MarkDone

func (s *Store) MarkDone(ctx context.Context, channel, messageID string) error

MarkDone marks an item fully processed (reply delivered) so it is not run or re-sent again.

func (*Store) Offset

func (s *Store) Offset(ctx context.Context, channel string) (int64, error)

Offset returns the persisted ack cursor for a polling channel, or 0 if none.

func (*Store) Pending

func (s *Store) Pending(ctx context.Context) ([]Item, error)

Pending returns the still-to-process items, oldest first. Used to feed the worker and, on startup, to replay anything a prior crash left unprocessed.

func (*Store) PendingReplies

func (s *Store) PendingReplies(ctx context.Context) ([]Item, error)

PendingReplies returns items whose job finished but whose reply has not yet been delivered, oldest first — the outbound retry queue, drained on every tick and replayed after a restart.

func (*Store) PruneDone

func (s *Store) PruneDone(ctx context.Context, before time.Time) error

PruneDone deletes processed items older than the cutoff, so the inbox can't grow without bound. Only 'done' rows are pruned; pending work is never dropped.

func (*Store) SetConversationAgent added in v0.13.0

func (s *Store) SetConversationAgent(ctx context.Context, channel, conversation, agent string) error

SetConversationAgent points a conversation at a persona for its SUBSEQUENT tasks (upsert, preserving the current project).

func (*Store) SetConversationProject added in v0.13.0

func (s *Store) SetConversationProject(ctx context.Context, channel, conversation, project string) error

SetConversationProject points a conversation at a project for its SUBSEQUENT tasks (upsert, preserving the current agent).

func (*Store) SetOffset

func (s *Store) SetOffset(ctx context.Context, channel string, offset int64) error

SetOffset durably records a polling channel's ack cursor.

func (*Store) SetReplied

func (s *Store) SetReplied(ctx context.Context, channel, messageID, reply string) error

SetReplied durably records a finished job's reply and moves the item to 'replied'. From here the job is never re-run; only the reply's delivery is retried, so a send failure or a crash after the job completes cannot lose the result or repeat the work.

Jump to

Keyboard shortcuts

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