watcher

package
v1.7.0 Latest Latest
Warning

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

Go to latest
Published: Feb 2, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package watcher provides file watching with debouncing using fsnotify. config.go provides helper functions to create watchers from config.

Package watcher provides file watching with debouncing using fsnotify. conflict.go defines types and callbacks for file reservation conflicts.

Package watcher provides file watching with debouncing.

Package watcher provides file watching with debouncing using fsnotify. file_reservation.go implements automatic file reservation based on pane output detection.

Package watcher provides file watching with debouncing using fsnotify.

Index

Constants

View Source
const (
	// DefaultPollIntervalReservation is the default polling interval for checking pane output.
	DefaultPollIntervalReservation = 10 * time.Second

	// DefaultIdleTimeout is how long a pane must be idle before releasing reservations.
	DefaultIdleTimeout = 10 * time.Minute

	// DefaultReservationTTL is the TTL for file reservations.
	DefaultReservationTTL = 15 * time.Minute

	// DefaultCaptureLinesReservation is the number of lines to capture for pattern detection.
	DefaultCaptureLinesReservation = 100
)
View Source
const DefaultDebounceDuration = 250 * time.Millisecond

DefaultDebounceDuration is the default debounce window.

View Source
const DefaultPollInterval = time.Second

DefaultPollInterval is used when falling back to polling.

Variables

View Source
var ErrClosed = errors.New("watcher: watcher is closed")

ErrClosed is returned when operations are called on a closed Watcher.

Functions

This section is empty.

Types

type ConflictAction

type ConflictAction int

ConflictAction represents the user's chosen action for a conflict.

const (
	// ConflictActionWait indicates the user chose to wait for the reservation to expire
	ConflictActionWait ConflictAction = iota
	// ConflictActionRequest indicates the user requested a handoff from the holder
	ConflictActionRequest
	// ConflictActionForce indicates the user chose to force-release the reservation
	ConflictActionForce
	// ConflictActionDismiss indicates the user dismissed the conflict without action
	ConflictActionDismiss
)

func (ConflictAction) String

func (a ConflictAction) String() string

String returns a human-readable name for the action.

type ConflictActionHandler

type ConflictActionHandler func(conflict FileConflict, action ConflictAction) error

ConflictActionHandler is called when the user selects an action for a conflict. Returns an error if the action could not be performed.

type ConflictCallback

type ConflictCallback func(conflict FileConflict)

ConflictCallback is called when a file reservation conflict is detected. Implementations should handle the conflict notification to the user.

type Debouncer

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

Debouncer coalesces rapid events into a single callback invocation. When Trigger is called multiple times within the debounce duration, only the last callback is executed after the duration elapses.

func NewDebouncer

func NewDebouncer(duration time.Duration) *Debouncer

NewDebouncer creates a new Debouncer with the specified duration. If duration is 0, DefaultDebounceDuration is used.

func (*Debouncer) Cancel

func (d *Debouncer) Cancel()

Cancel cancels any pending callback.

func (*Debouncer) Duration

func (d *Debouncer) Duration() time.Duration

Duration returns the debounce duration.

func (*Debouncer) Reset

func (d *Debouncer) Reset(duration time.Duration)

Reset changes the debounce duration and cancels any pending callback.

func (*Debouncer) Trigger

func (d *Debouncer) Trigger(callback func())

Trigger schedules the callback to be called after the debounce duration. If Trigger is called again before the duration elapses, the previous scheduled callback is canceled and a new one is scheduled.

type ErrorHandler

type ErrorHandler func(err error)

ErrorHandler is called when a watch error occurs.

type Event

type Event struct {
	// Path is the absolute path to the file or directory.
	Path string
	// Type is the type of event.
	Type EventType
	// IsDir is true if the event is for a directory.
	IsDir bool
}

Event represents a file system event.

type EventType

type EventType uint32

EventType represents the type of file system event.

const (
	// Create is triggered when a file or directory is created.
	Create EventType = 1 << iota
	// Write is triggered when a file is modified.
	Write
	// Remove is triggered when a file or directory is removed.
	Remove
	// Rename is triggered when a file or directory is renamed.
	Rename
	// Chmod is triggered when file permissions change.
	Chmod
	// All events.
	All = Create | Write | Remove | Rename | Chmod
)

type FileConflict

type FileConflict struct {
	// Path is the file path that caused the conflict
	Path string `json:"path"`

	// RequestorAgent is the agent that tried to edit the file
	RequestorAgent string `json:"requestor_agent"`

	// RequestorPane is the pane ID of the requestor
	RequestorPane string `json:"requestor_pane"`

	// SessionName is the tmux session name
	SessionName string `json:"session_name"`

	// Holders are the agents currently holding the reservation
	Holders []string `json:"holders"`

	// HolderReservationIDs are the reservation IDs held by the holders (for force-release)
	HolderReservationIDs []int `json:"holder_reservation_ids,omitempty"`

	// ReservedSince is when the file was reserved (if known)
	ReservedSince *time.Time `json:"reserved_since,omitempty"`

	// ExpiresAt is when the reservation expires (if known)
	ExpiresAt *time.Time `json:"expires_at,omitempty"`

	// DetectedAt is when this conflict was detected
	DetectedAt time.Time `json:"detected_at"`
}

FileConflict represents a detected file reservation conflict. This occurs when an agent attempts to edit a file that is reserved by another agent.

func (*FileConflict) IsExpired

func (c *FileConflict) IsExpired() bool

IsExpired returns true if the reservation has expired. Returns false if expiry time is unknown (assume still active).

func (*FileConflict) TimeRemaining

func (c *FileConflict) TimeRemaining() time.Duration

TimeRemaining returns how much time is left until the reservation expires. Returns 0 if the reservation has expired or expiry time is unknown.

func (*FileConflict) TimeSinceReserved

func (c *FileConflict) TimeSinceReserved() time.Duration

TimeSinceReserved returns how long the file has been reserved. Returns 0 if the reservation start time is unknown.

type FileReservationConfigValues

type FileReservationConfigValues struct {
	Enabled               bool
	AutoReserve           bool
	AutoReleaseIdleMin    int
	NotifyOnConflict      bool
	ExtendOnActivity      bool
	DefaultTTLMin         int
	PollIntervalSec       int
	CaptureLinesForDetect int
	Debug                 bool
}

FileReservationConfigValues holds the values needed to configure a FileReservationWatcher. This struct avoids import cycles by using primitive types instead of config.FileReservationConfig.

func DefaultFileReservationConfigValues

func DefaultFileReservationConfigValues() FileReservationConfigValues

DefaultFileReservationConfigValues returns the default values for file reservation config. Use this when config is not available or as a fallback.

type FileReservationWatcher

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

FileReservationWatcher monitors pane output and automatically reserves files.

func NewFileReservationWatcher

func NewFileReservationWatcher(opts ...FileReservationWatcherOption) *FileReservationWatcher

NewFileReservationWatcher creates a new FileReservationWatcher.

func NewFileReservationWatcherFromConfig

func NewFileReservationWatcherFromConfig(
	cfg FileReservationConfigValues,
	client *agentmail.Client,
	projectDir string,
	agentName string,
	conflictCallback ConflictCallback,
) *FileReservationWatcher

NewFileReservationWatcherFromConfig creates a FileReservationWatcher configured from the provided config values.

func (*FileReservationWatcher) GetActiveReservations

func (w *FileReservationWatcher) GetActiveReservations() map[string]*PaneReservation

GetActiveReservations returns a copy of all active reservations.

func (*FileReservationWatcher) OnFileEdit

func (w *FileReservationWatcher) OnFileEdit(ctx context.Context, sessionName string, pane tmux.Pane, files []string)

OnFileEdit handles detected file edits by reserving files.

func (*FileReservationWatcher) RenewReservations

func (w *FileReservationWatcher) RenewReservations(ctx context.Context) error

RenewReservations extends the TTL of all active reservations.

func (*FileReservationWatcher) Start

func (w *FileReservationWatcher) Start(ctx context.Context)

Start begins the file reservation watcher in a background goroutine.

func (*FileReservationWatcher) Stop

func (w *FileReservationWatcher) Stop()

Stop halts the file reservation watcher and releases all reservations.

type FileReservationWatcherOption

type FileReservationWatcherOption func(*FileReservationWatcher)

FileReservationWatcherOption configures a FileReservationWatcher.

func WithAgentName

func WithAgentName(name string) FileReservationWatcherOption

WithAgentName sets the agent name for reservations.

func WithCaptureLines

func WithCaptureLines(lines int) FileReservationWatcherOption

WithCaptureLines sets the number of lines to capture for pattern detection.

func WithConflictCallback

func WithConflictCallback(cb ConflictCallback) FileReservationWatcherOption

WithConflictCallback sets the callback for conflict notifications.

func WithDebug

func WithDebug(debug bool) FileReservationWatcherOption

WithDebug enables debug logging.

func WithIdleTimeout

func WithIdleTimeout(d time.Duration) FileReservationWatcherOption

WithIdleTimeout sets the idle timeout for releasing reservations.

func WithProjectDir

func WithProjectDir(dir string) FileReservationWatcherOption

WithProjectDir sets the project directory.

func WithReservationPollInterval

func WithReservationPollInterval(d time.Duration) FileReservationWatcherOption

WithReservationPollInterval sets the polling interval.

func WithReservationTTL

func WithReservationTTL(d time.Duration) FileReservationWatcherOption

WithReservationTTL sets the TTL for reservations.

func WithWatcherClient

func WithWatcherClient(client *agentmail.Client) FileReservationWatcherOption

WithWatcherClient sets the Agent Mail client.

type Handler

type Handler func(events []Event)

Handler is called when a file system event occurs. Multiple events may be coalesced into a single call due to debouncing.

type Option

type Option func(*Watcher)

Option configures a Watcher.

func WithDebounceDuration

func WithDebounceDuration(d time.Duration) Option

WithDebounceDuration sets the debounce duration for coalescing events. Use a real time.Duration to avoid hidden unit conversions.

func WithDebouncer

func WithDebouncer(d *Debouncer) Option

WithDebouncer sets a custom debouncer.

func WithErrorHandler

func WithErrorHandler(handler ErrorHandler) Option

WithErrorHandler sets the error handler.

func WithEventFilter

func WithEventFilter(filter EventType) Option

WithEventFilter sets which event types to watch.

func WithIgnorePaths

func WithIgnorePaths(patterns []string) Option

WithIgnorePaths sets patterns to ignore (matched against file/dir name).

func WithPollInterval

func WithPollInterval(d time.Duration) Option

WithPollInterval sets the polling interval (used when polling mode is active).

func WithPolling

func WithPolling(force bool) Option

WithPolling forces polling mode (useful for tests or environments without fsnotify support).

func WithRecursive

func WithRecursive(recursive bool) Option

WithRecursive enables recursive watching of directories.

type PaneReservation

type PaneReservation struct {
	PaneID        string
	AgentName     string
	Files         []string
	ReservationID []int
	LastActivity  time.Time
	LastOutput    string // Hash or truncated output to detect changes
}

PaneReservation tracks reservations made by a pane.

type Watcher

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

Watcher watches files and directories for changes.

func New

func New(handler Handler, opts ...Option) (*Watcher, error)

New creates a new Watcher. By default, all event types are watched. Use WithEventFilter to filter events. Use WithRecursive to watch directories recursively.

func (*Watcher) Add

func (w *Watcher) Add(path string) error

Add adds a path to the watcher. If the path is a directory and recursive is enabled, all subdirectories are also watched.

func (*Watcher) Close

func (w *Watcher) Close() error

Close stops the watcher and releases resources.

func (*Watcher) Remove

func (w *Watcher) Remove(path string) error

Remove removes a path from the watcher.

func (*Watcher) WatchedPaths

func (w *Watcher) WatchedPaths() []string

WatchedPaths returns a slice of all currently watched paths.

Jump to

Keyboard shortcuts

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