processctl

package
v0.12.1 Latest Latest
Warning

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

Go to latest
Published: May 14, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package processctl owns the in-process lifecycle of the HTTP server and background worker: Start/Stop/IsRunning + a per-process IsManaged flag that says whether wick was launched via the system tray (and is therefore allowed to mutate its own server/worker state).

Two consumers:

  • internal/systemtray — calls Start/Stop on menu clicks and subscribes to OnStateChange so tray UI redraws when state flips.
  • internal/connectors/wickmanager — exposes Start/Stop/Status as MCP ops gated by IsManaged so an LLM can only manage server/ worker when wick is actually the tray-resident process. `wick server` / `wick worker` / headless modes leave IsManaged=false so the ops return "system management unavailable in this run mode".

Implementation lives in headless-build-tagged files so the headless build (no tray) compiles a stub that always reports IsManaged=false and refuses Start/Stop. Tray boot calls SetManaged(true) once.

Index

Constants

This section is empty.

Variables

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

ErrAlreadyRunning is returned by Server.Start / Worker.Start when the component is already up. Callers check via errors.Is so wickmanager can map it to a stable error string for the LLM.

View Source
var ErrNotManaged = errors.New("system management unavailable in this run mode (start wick via the tray)")

ErrNotManaged is returned by every state-mutating method when the process was not launched via the tray. wick server / wick worker / headless never satisfy IsManaged.

Functions

func IsManaged

func IsManaged() bool

IsManaged reports whether the current process is the tray-resident one. wickmanager's tray-only ops gate on this.

func IsServerRunning

func IsServerRunning() bool

IsServerRunning reports whether the server goroutine is up.

func IsWorkerRunning

func IsWorkerRunning() bool

IsWorkerRunning reports whether the worker goroutine is up.

func MCPLogger

func MCPLogger() (zerolog.Logger, bool)

MCPLogger returns the wickmanager audit logger configured via SetMCPLogger. The bool is false when no logger was set; callers then default to log.Logger / zerolog.Ctx(ctx).

func ServerPort

func ServerPort() int

ServerPort returns the configured listen port. 0 before SetPort.

func SetMCPLogger

func SetMCPLogger(l zerolog.Logger)

SetMCPLogger configures the destination for the wickmanager connector's audit log (~/.<appName>/logs/mcp-YYYY-MM-DD.log). Tray calls this after opening the log file; non-tray callers (wick server / headless) leave it at zero, in which case wickmanager falls back to the global zerolog logger.

func SetManaged

func SetManaged(v bool)

SetManaged marks the current process as the tray-resident one. Called once from systemtray.Run before any Start/Stop is reachable. Other entry points (wick server / wick worker / headless) never call this, so IsManaged stays false there.

func SetPort

func SetPort(port int)

SetPort configures the HTTP listen port StartServer will bind. Tray resolves config.Load().App.Port at boot and passes it in here.

func SetServerLogger

func SetServerLogger(l zerolog.Logger)

SetServerLogger configures the zerolog.Logger threaded through every future server.Run context. Tray calls this with its server-log file writer; wickmanager-only callers (no tray) leave it at the default.

func SetServerRunner

func SetServerRunner(r Runner)

SetServerRunner installs the runner StartServer launches. Tray wires this to api.NewServer with its port closed-over; non-tray callers (wick server / wick worker / headless) never call it.

func SetWorkerLogger

func SetWorkerLogger(l zerolog.Logger)

SetWorkerLogger is the worker-side counterpart to SetServerLogger.

func SetWorkerRunner

func SetWorkerRunner(r Runner)

SetWorkerRunner installs the runner StartWorker launches. Tray wires this to worker.NewServer.

func StartServer

func StartServer() error

StartServer launches the HTTP server in this process. Returns ErrAlreadyRunning when one is already up, ErrNotManaged when the process is not tray-resident, or a wrapped bind error when the pre-flight listener check fails.

func StartWorker

func StartWorker() error

StartWorker launches the background worker in this process. Returns ErrAlreadyRunning / ErrNotManaged the same way StartServer does.

func StopAll

func StopAll()

StopAll halts both. Used by tray Quit and the updater's apply-then- restart path. Ignores ErrNotManaged so non-tray callers (which shouldn't reach here) get a no-op.

func StopServer

func StopServer() error

StopServer cancels the server goroutine and waits for it to drain. No-op when nothing is running. Always reports nil — used by tray menu and wickmanager system_server_stop.

func StopWorker

func StopWorker() error

StopWorker cancels the worker goroutine and waits for it to drain. No-op when nothing is running.

func Subscribe

func Subscribe(fn func(StateChange)) func()

Subscribe registers a callback fired after every Start/Stop. Used by the tray to refresh its icon + menu labels — non-tray callers don't subscribe. Returned func unsubscribes.

Types

type Runner

type Runner interface {
	Run(ctx context.Context) error
}

Runner is the contract a server / worker must satisfy. Both internal/pkg/api.Server and internal/pkg/worker.Server already implement it via their existing Run(ctx) signatures (api.Server.Run also takes a port; the tray wraps it before plugging in here).

processctl owns the goroutine + cancel handle and never calls NewServer itself — that keeps internal/pkg/api and internal/pkg/ worker free to import processctl when they need IsManaged without dragging the whole runtime through an import cycle.

type RunnerFunc

type RunnerFunc func(ctx context.Context) error

RunnerFunc adapts a closure to Runner. Tray uses it to wrap api.NewServer().Run with the configured port:

processctl.SetServerRunner(processctl.RunnerFunc(func(ctx context.Context) error {
    return api.NewServer().Run(ctx, processctl.ServerPort())
}))

func (RunnerFunc) Run

func (f RunnerFunc) Run(ctx context.Context) error

type StateChange

type StateChange struct {
	ServerRunning bool
	ServerPort    int
	WorkerRunning bool
}

StateChange is the event payload sent on every state transition. The tray subscribes to refresh its menu icon + labels; wickmanager does not subscribe (it polls IsRunning at op-call time).

Jump to

Keyboard shortcuts

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