daemon

package
v0.12.2 Latest Latest
Warning

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

Go to latest
Published: Apr 26, 2026 License: MIT Imports: 28 Imported by: 0

Documentation

Index

Constants

View Source
const CurrentStateVersion = 1

Variables

View Source
var ErrDaemonRunning = errors.New("daemon already running")

Functions

func AcquirePIDFile

func AcquirePIDFile(path string) error

func ExecUpgrade

func ExecUpgrade(manifestPath, configFile string) error

func HandleConnection

func HandleConnection(ctx context.Context, conn net.Conn, sm *SessionManager, log *slog.Logger)

HandleConnection processes the frame protocol for a single client connection.

func Listen

func Listen(sockPath string) (net.Listener, error)

func ReleasePIDFile

func ReleasePIDFile(path string)

func Run

func Run(cfg *config.Config, paths config.Paths, configFile, adoptFrom string) error

Run starts the daemon: acquires PID file, listens on the Unix socket, serves connections, and blocks until SIGTERM/SIGINT or an upgrade signal.

func SaveState

func SaveState(path string, state *State) error

func StopDaemon

func StopDaemon(pidFile string) error

func WriteManifest

func WriteManifest(dir string, m *UpgradeManifest) (string, error)

Types

type Message

type Message struct {
	ID         string `json:"id"`
	Seq        int64  `json:"seq"`
	Stream     string `json:"stream"`
	SenderID   string `json:"sender_id"`
	SenderName string `json:"sender_name,omitempty"`
	Body       string `json:"body"`
	ThreadID   string `json:"thread_id,omitempty"`
	ReplyTo    string `json:"reply_to,omitempty"`
	CreatedAt  string `json:"created_at"`
}

type MsgStore

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

func NewMsgStore

func NewMsgStore(dbPath string) (*MsgStore, error)

func (*MsgStore) Ack

func (s *MsgStore) Ack(stream, subscriber string, upToSeq int64) error

func (*MsgStore) AckLatest

func (s *MsgStore) AckLatest(stream, subscriber string) error

func (*MsgStore) Cleanup added in v0.3.0

func (s *MsgStore) Cleanup(maxAge time.Duration, maxPerStream int) (int64, error)

func (*MsgStore) Close

func (s *MsgStore) Close() error

func (*MsgStore) ListStreams

func (s *MsgStore) ListStreams(subscriber string) ([]StreamInfo, error)

func (*MsgStore) Publish

func (s *MsgStore) Publish(stream, senderID, senderName, body, threadID, replyTo string) (Message, error)

func (*MsgStore) Read

func (s *MsgStore) Read(stream, subscriber string, onlyUnread bool, threadID string) ([]Message, error)

func (*MsgStore) Subscribe

func (s *MsgStore) Subscribe(stream string) (chan Message, func())

func (*MsgStore) TotalUnread added in v0.3.0

func (s *MsgStore) TotalUnread(subscriber string) int

type Server

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

func NewServer

func NewServer(l net.Listener, handler func(ctx context.Context, conn net.Conn), log *slog.Logger) *Server

func (*Server) Serve

func (s *Server) Serve(ctx context.Context) error

func (*Server) Shutdown

func (s *Server) Shutdown()

type SessionManager

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

SessionManager orchestrates PTY sessions, state persistence, and git worktrees.

func NewSessionManager

func NewSessionManager(cfg *config.Config, paths config.Paths, log *slog.Logger) *SessionManager

NewSessionManager creates a SessionManager with the given config and paths.

func (*SessionManager) AdoptSessions

func (sm *SessionManager) AdoptSessions(manifest *UpgradeManifest) error

func (*SessionManager) ClearAttachedClient

func (sm *SessionManager) ClearAttachedClient(sessionID string, conn net.Conn)

func (*SessionManager) Create

func (sm *SessionManager) Create(name, agentName, repoPath, baseBranch, prompt string, noRepo bool, rows, cols uint16) (SessionState, error)

Create starts a new agent session, either in a git worktree or as a standalone scratch session (when noRepo is true).

func (*SessionManager) Delete

func (sm *SessionManager) Delete(id string) error

Delete stops a session, removes its worktree/branch, and deletes state.

func (*SessionManager) FindByName

func (sm *SessionManager) FindByName(name string) (SessionState, bool)

FindByName looks up a session by exact name, then by prefix match.

func (*SessionManager) Fork added in v0.10.0

func (sm *SessionManager) Fork(name, sourceSessionID string, rows, cols uint16) (SessionState, error)

Fork creates a new session that branches from an existing session's git state and uses the agent's fork_args to carry over the conversation history.

func (*SessionManager) Get

func (sm *SessionManager) Get(id string) (SessionState, bool)

Get returns a copy of a session state by ID.

func (*SessionManager) GetPTY

func (sm *SessionManager) GetPTY(id string) (*grpty.Session, bool)

GetPTY returns the live PTY session by ID.

func (*SessionManager) HandleHookReport added in v0.11.0

func (sm *SessionManager) HandleHookReport(sr protocol.StatusReportMsg)

HandleHookReport processes a status report from an agent hook, updating the in-memory hookReports map and the session's AgentStatus. This is the authoritative source of agent status when hooks are active.

func (*SessionManager) KickAttachedClient

func (sm *SessionManager) KickAttachedClient(sessionID string)

func (*SessionManager) List

func (sm *SessionManager) List() []SessionState

List returns copies of all known session states.

func (*SessionManager) LoadState

func (sm *SessionManager) LoadState() error

LoadState reads persisted state from disk and reconciles dead processes.

func (*SessionManager) PrepareUpgrade

func (sm *SessionManager) PrepareUpgrade(listenerFd uintptr, configFile string) (*UpgradeManifest, error)

func (*SessionManager) ReloadConfig added in v0.3.0

func (sm *SessionManager) ReloadConfig() error

ReloadConfig loads the config from disk and swaps it in, logging what changed.

func (*SessionManager) Rename

func (sm *SessionManager) Rename(id, newName string) error

Rename changes the display name of a session.

func (*SessionManager) Resume

func (sm *SessionManager) Resume(id string, rows, cols uint16) (SessionState, error)

Resume restarts a stopped session using the agent's resume_args.

func (*SessionManager) RunDetectionLoop

func (sm *SessionManager) RunDetectionLoop(ctx context.Context)

RunDetectionLoop periodically scans PTY scrollback to detect agent status (active, needs approval, ready) for all running sessions.

func (*SessionManager) RunMessageCleanupLoop added in v0.3.0

func (sm *SessionManager) RunMessageCleanupLoop(ctx context.Context)

func (*SessionManager) SetAttachedClient

func (sm *SessionManager) SetAttachedClient(sessionID string, conn net.Conn, kick func())

func (*SessionManager) SetMsgStore

func (sm *SessionManager) SetMsgStore(ms *MsgStore)

func (*SessionManager) Stop

func (sm *SessionManager) Stop(id string) error

Stop sends SIGTERM to a session's process without removing the session or worktree.

func (*SessionManager) StopAll

func (sm *SessionManager) StopAll(ctx context.Context)

StopAll gracefully terminates all running sessions.

type SessionState

type SessionState struct {
	ID                 string        `json:"id"`
	Name               string        `json:"name"`
	RepoPath           string        `json:"repo_path"`
	RepoName           string        `json:"repo_name"`
	WorktreePath       string        `json:"worktree_path"`
	Branch             string        `json:"branch"`
	BaseBranch         string        `json:"base_branch"`
	Agent              string        `json:"agent"`
	AgentSessionID     string        `json:"agent_session_id,omitempty"`
	Status             SessionStatus `json:"status"`
	AgentStatus        string        `json:"agent_status,omitempty"`
	IdleSince          *time.Time    `json:"-"`
	GitDirty           bool          `json:"-"`
	GitUnpushed        int           `json:"-"`
	HookModel          string        `json:"-"`
	HookToolName       string        `json:"-"`
	HookCostUSD        *float64      `json:"-"`
	HookContextPercent *float64      `json:"-"`
	ExitCode           *int          `json:"exit_code,omitempty"`
	PID                int           `json:"pid,omitempty"`
	Sandboxed          bool          `json:"sandboxed,omitempty"`
	CreatedAt          time.Time     `json:"created_at"`
	LastAttachedAt     *time.Time    `json:"last_attached_at,omitempty"`
}

type SessionStatus

type SessionStatus string
const (
	StatusRunning SessionStatus = "running"
	StatusStopped SessionStatus = "stopped"
	StatusErrored SessionStatus = "errored"
)

type State

type State struct {
	Version  int                      `json:"version"`
	Sessions map[string]*SessionState `json:"sessions"`
}

func LoadState

func LoadState(path string) (*State, error)

func NewState

func NewState() *State

func (*State) Reconcile

func (s *State) Reconcile()

type StreamInfo

type StreamInfo struct {
	Name     string `json:"name"`
	Total    int64  `json:"total"`
	Unread   int64  `json:"unread"`
	LatestAt string `json:"latest_at,omitempty"`
}

type UpgradeManifest

type UpgradeManifest struct {
	ListenerFd int              `json:"listener_fd"`
	ConfigFile string           `json:"config_file"`
	Sessions   []UpgradeSession `json:"sessions"`
}

func ReadManifest

func ReadManifest(path string) (*UpgradeManifest, error)

type UpgradeSession

type UpgradeSession struct {
	ID  string `json:"id"`
	Fd  int    `json:"fd"`
	PID int    `json:"pid"`
}

Jump to

Keyboard shortcuts

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