daemon

package
v0.6.2 Latest Latest
Warning

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

Go to latest
Published: Feb 11, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package daemon provides a client interface for interacting with the Grove Daemon (groved). It implements a transparent fallback pattern: if the daemon is running, use RPC; if not, fall back to direct library calls.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

type Client interface {
	// GetWorkspaces returns all discovered workspaces.
	GetWorkspaces(ctx context.Context) ([]*workspace.WorkspaceNode, error)

	// GetEnrichedWorkspaces returns workspaces with enrichment data.
	GetEnrichedWorkspaces(ctx context.Context, opts *enrichment.EnrichmentOptions) ([]*enrichment.EnrichedWorkspace, error)

	// GetPlanStats returns aggregated plan statistics indexed by workspace path.
	GetPlanStats(ctx context.Context) (map[string]*enrichment.PlanStats, error)

	// GetNoteCounts returns aggregated note counts indexed by workspace name.
	GetNoteCounts(ctx context.Context) (map[string]*enrichment.NoteCounts, error)

	// GetSessions returns active sessions from all sources.
	GetSessions(ctx context.Context) ([]*models.Session, error)

	// StreamState subscribes to real-time state updates from the daemon.
	// Returns a channel that receives updates and a function to stop the stream.
	// For LocalClient, this returns an error since streaming is only available via daemon.
	StreamState(ctx context.Context) (<-chan StateUpdate, error)

	// GetConfig returns the running configuration of the daemon.
	// For LocalClient, this returns an error since config is only available via daemon.
	GetConfig(ctx context.Context) (*RunningConfig, error)

	// SetFocus tells the daemon which workspaces to prioritize for scanning.
	// For LocalClient, this is a no-op since there's no daemon to notify.
	SetFocus(ctx context.Context, paths []string) error

	// Refresh triggers a re-scan of workspaces and enrichment data.
	// For LocalClient, this is a no-op since there's no daemon cache to refresh.
	// For RemoteClient, this signals the daemon to immediately re-discover workspaces.
	Refresh(ctx context.Context) error

	// IsRunning returns true if the daemon is available and responding.
	IsRunning() bool

	// Close cleans up any resources used by the client.
	Close() error
}

Client defines the interface for interacting with the Grove Daemon. Both DaemonClient (RPC) and LocalClient (direct calls) implement this interface.

func MustConnect

func MustConnect() Client

MustConnect returns a DaemonClient or panics if the daemon is not available. Use this in contexts where the daemon is required (e.g., daemon-only tools).

func New

func New() Client

New returns a Client that will use the daemon if available, otherwise falls back to LocalClient.

This implements the "transparent daemon" pattern: callers don't need to know whether the daemon is running or not. The same API works in both modes.

type LocalClient

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

LocalClient implements Client by calling library functions directly. This is used when the daemon is not running, providing the same API but executing all operations in-process.

func NewLocalClient

func NewLocalClient() *LocalClient

NewLocalClient creates a new LocalClient.

func (*LocalClient) Close

func (c *LocalClient) Close() error

Close is a no-op for LocalClient.

func (*LocalClient) GetConfig

func (c *LocalClient) GetConfig(ctx context.Context) (*RunningConfig, error)

GetConfig returns an error for LocalClient since config is only available via daemon.

func (*LocalClient) GetEnrichedWorkspaces

func (c *LocalClient) GetEnrichedWorkspaces(ctx context.Context, opts *enrichment.EnrichmentOptions) ([]*enrichment.EnrichedWorkspace, error)

GetEnrichedWorkspaces returns workspaces with enrichment data.

func (*LocalClient) GetNoteCounts

func (c *LocalClient) GetNoteCounts(ctx context.Context) (map[string]*enrichment.NoteCounts, error)

GetNoteCounts returns aggregated note counts.

func (*LocalClient) GetPlanStats

func (c *LocalClient) GetPlanStats(ctx context.Context) (map[string]*enrichment.PlanStats, error)

GetPlanStats returns aggregated plan statistics.

func (*LocalClient) GetSessions

func (c *LocalClient) GetSessions(ctx context.Context) ([]*models.Session, error)

GetSessions returns active sessions from all sources. This uses the comprehensive DiscoverAll function which aggregates: - Interactive sessions (from ~/.grove/hooks/sessions) - Flow jobs (from workspace plan/chat/note directories) - OpenCode sessions (from ~/.local/share/opencode/storage)

This provides full parity with the daemon's session registry when running in local mode.

func (*LocalClient) GetWorkspaces

func (c *LocalClient) GetWorkspaces(ctx context.Context) ([]*workspace.WorkspaceNode, error)

GetWorkspaces returns all discovered workspaces by calling the discovery service directly.

func (*LocalClient) IsRunning

func (c *LocalClient) IsRunning() bool

IsRunning returns false since this is the local fallback client.

func (*LocalClient) Refresh

func (c *LocalClient) Refresh(ctx context.Context) error

Refresh is a no-op for LocalClient since there's no daemon cache to refresh.

func (*LocalClient) SetFocus

func (c *LocalClient) SetFocus(ctx context.Context, paths []string) error

SetFocus is a no-op for LocalClient since there's no daemon to notify.

func (*LocalClient) StreamState

func (c *LocalClient) StreamState(ctx context.Context) (<-chan StateUpdate, error)

StreamState returns an error for LocalClient since streaming is only available via daemon. Use the daemon for real-time updates.

type RemoteClient

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

RemoteClient implements Client by calling the daemon's HTTP API over a Unix socket. This provides fast, cached access to workspace and session data when the daemon is running.

func NewRemoteClient

func NewRemoteClient(socketPath string) (*RemoteClient, error)

NewRemoteClient creates a new RemoteClient connected to the daemon socket.

func (*RemoteClient) Close

func (c *RemoteClient) Close() error

Close cleans up any resources used by the client.

func (*RemoteClient) GetConfig

func (c *RemoteClient) GetConfig(ctx context.Context) (*RunningConfig, error)

GetConfig returns the running configuration of the daemon.

func (*RemoteClient) GetEnrichedWorkspaces

func (c *RemoteClient) GetEnrichedWorkspaces(ctx context.Context, opts *enrichment.EnrichmentOptions) ([]*enrichment.EnrichedWorkspace, error)

GetEnrichedWorkspaces returns workspaces with enrichment data from the daemon.

func (*RemoteClient) GetNoteCounts

func (c *RemoteClient) GetNoteCounts(ctx context.Context) (map[string]*enrichment.NoteCounts, error)

GetNoteCounts returns aggregated note counts indexed by workspace name. Extracts NoteCounts from enriched workspaces.

func (*RemoteClient) GetPlanStats

func (c *RemoteClient) GetPlanStats(ctx context.Context) (map[string]*enrichment.PlanStats, error)

GetPlanStats returns aggregated plan statistics indexed by workspace path. Extracts PlanStats from enriched workspaces.

func (*RemoteClient) GetSessions

func (c *RemoteClient) GetSessions(ctx context.Context) ([]*models.Session, error)

GetSessions returns active sessions from the daemon.

func (*RemoteClient) GetWorkspaces

func (c *RemoteClient) GetWorkspaces(ctx context.Context) ([]*workspace.WorkspaceNode, error)

GetWorkspaces returns all discovered workspaces by extracting WorkspaceNode from enriched workspaces.

func (*RemoteClient) IsRunning

func (c *RemoteClient) IsRunning() bool

IsRunning returns true if the daemon is available and responding.

func (*RemoteClient) Refresh

func (c *RemoteClient) Refresh(ctx context.Context) error

Refresh triggers a re-scan of workspaces and enrichment data.

func (*RemoteClient) SetFocus

func (c *RemoteClient) SetFocus(ctx context.Context, paths []string) error

SetFocus tells the daemon which workspaces to prioritize for scanning.

func (*RemoteClient) StreamState

func (c *RemoteClient) StreamState(ctx context.Context) (<-chan StateUpdate, error)

StreamState subscribes to real-time state updates via Server-Sent Events (SSE). Returns a channel that receives updates. The channel is closed when the context is cancelled or the connection is lost.

type RunningConfig

type RunningConfig struct {
	GitInterval       time.Duration `json:"git_interval"`
	SessionInterval   time.Duration `json:"session_interval"`
	WorkspaceInterval time.Duration `json:"workspace_interval"`
	PlanInterval      time.Duration `json:"plan_interval"`
	NoteInterval      time.Duration `json:"note_interval"`
	StartedAt         time.Time     `json:"started_at"`
}

RunningConfig holds the active configuration intervals being used by the daemon.

type StateUpdate

type StateUpdate struct {
	Workspaces []*enrichment.EnrichedWorkspace `json:"workspaces,omitempty"`
	Sessions   []*models.Session               `json:"sessions,omitempty"`
	UpdateType string                          `json:"update_type"`       // "full", "workspace", "session", "enrichment"
	Source     string                          `json:"source,omitempty"`  // Which collector sent this update (e.g., "git", "workspace", "session", "plan", "note")
	Scanned    int                             `json:"scanned,omitempty"` // Number of items actually scanned (for focused updates)
}

StateUpdate represents an update pushed from the daemon to subscribers.

type WithFallback

type WithFallback struct {
	Primary  Client
	Fallback Client
}

WithFallback wraps a Client to provide graceful degradation. If the primary client fails, it falls back to LocalClient.

func NewWithFallback

func NewWithFallback() *WithFallback

NewWithFallback creates a client that tries the daemon first, then falls back to local execution.

Jump to

Keyboard shortcuts

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