version

package
v0.22.37 Latest Latest
Warning

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

Go to latest
Published: Apr 29, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package version — daemon-side periodic update poller. Every `Interval` ticks (default 1h) the poller calls `CheckForUpdate`; when a transition from no-update → update-available is detected it broadcasts a SystemNotification onto the supplied publisher (typically biam.WatchHub.BroadcastSystem). Connected watchers — orchestrator, dashboard, `task watch`, MCP clients dialling the watch socket — render the inline banner immediately, no polling.

Why daemon-side rather than per-CLI: the CLI is short-lived; the daemon (`clawtool serve`) is the long-running process the operator already keeps up. One canonical poller, single GitHub round-trip per host per hour, push to every active surface.

Telemetry: each transition emits a `clawtool.update_check` event with the same allow-listed payload SessionStart uses, so the operator gets a unified PostHog view of update detection across surfaces.

Package version — update-check primitive. Hits the GitHub Releases API for the latest tag and reports whether the local build is older. Cached for 24h in ~/.cache/clawtool/update.json so a `clawtool doctor` (or any other surface that calls CheckForUpdate) doesn't pay a network roundtrip on every invocation.

No background polling, no telemetry — this is a stateless, user-initiated check. The cache exists purely to avoid being rude to the GitHub API.

Package version exposes the clawtool build version.

Three layers, picked in order:

  1. ldflags override — `go build -ldflags='-X github.com/cogitave/clawtool/internal/version.Version=v…'`. goreleaser sets this on every release tarball, so installed binaries always carry the exact tag.

  2. runtime/debug.ReadBuildInfo — module-cached `go install` binaries surface the tag here. Local `go build` from a working tree returns "(devel)".

  3. The release-please-tracked constant below — fallback for dev workflows where neither (1) nor (2) yields a real version.

`Resolved()` is the single function every caller (overview, upgrade, claude-bootstrap, telemetry) must use to read the effective version. Reading `Version` directly (the constant) will diverge from what the binary actually is when goreleaser stamped a different value via ldflags.

Index

Constants

View Source
const Name = "clawtool"

x-release-please-start-version

View Source
const UpdateCheckURL = "https://api.github.com/repos/cogitave/clawtool/releases/latest"

UpdateCheckURL is the GitHub Releases API endpoint we hit. The public API permits ~60 unauthenticated requests/hour per IP; the 24h cache keeps us well under that even on shared CI runners.

Variables

View Source
var Version = "0.21.7" // x-release-please-version

Version is the build-stamped semver string. Declared as `var` (not `const`) so goreleaser can override it via `-ldflags='-X github.com/cogitave/clawtool/internal/version.Version=…'` at link time. `-X` cannot patch constants; that's why this is a var even though it's effectively immutable at runtime.

Functions

func Resolved added in v0.22.8

func Resolved() string

Resolved returns the authoritative installed-binary version. First-call computation is cached for the process lifetime — the binary's version doesn't change while it's running.

Output strips any leading "v" so callers can pass it straight into Compare() without normalising at every call site.

**Every external surface MUST use this** — telemetry events, hook payloads, /v1/health JSON, A2A card, doctor banner, orchestrator probe, MCP serverInfo. The literal `Version` var holds the pre-build fallback ("0.21.7") and reads of it outside this package are an anti-pattern: a goreleaser-baked binary at v0.22.34 emitting the const looks like v0.21.7 to every consumer (operator's PostHog filter, A2A peer, /v1/health probe — all silently wrong). The bug repeated across 9 sites before the operator caught it on 2026-04-29 ("12 hours, no telemetry events"). Don't repeat it — call Resolved().

func String

func String() string

String is the formatted "clawtool X.Y.Z" banner the CLI prints.

Types

type Poller added in v0.22.9

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

Poller wraps the periodic update probe + publisher. Lifetime = daemon process. Stop via ctx cancellation.

func NewPoller added in v0.22.9

func NewPoller(pub PublishFn, cfg PollerConfig, track func(outcome string)) *Poller

NewPoller constructs the poller with the given publisher and optional telemetry tracker. `track` is called on every check with the outcome enum ("up_to_date" | "update_available" | "check_failed"); pass nil to skip telemetry.

func (*Poller) Run added in v0.22.9

func (p *Poller) Run(ctx context.Context)

Run blocks until ctx cancels, ticking once per Interval. The first check fires immediately so a fresh daemon catches an already-pending update without waiting an hour.

type PollerConfig added in v0.22.9

type PollerConfig struct {
	// Interval between checks. Default 1h. Tests pass 50ms.
	Interval time.Duration
	// Timeout per HTTP round-trip. Default 5s.
	Timeout time.Duration
	// Now overrides time.Now for deterministic testing of
	// transitions. Production passes nil.
	Now func() time.Time
}

PollerConfig overrides the defaults — useful for tests that need a tighter tick. Empty struct = production defaults.

type PublishFn added in v0.22.9

type PublishFn func(kind, severity, title, body, actionHint string)

PublishFn is the slim function shape the poller needs from the caller. server.go wraps biam.WatchHub.BroadcastSystem; tests pass a recorder closure. Keeping this as a function instead of an interface avoids dragging biam into the version package's import graph (version stays a leaf).

type UpdateInfo added in v0.9.0

type UpdateInfo struct {
	// HasUpdate is true when the upstream tag is newer than the
	// local build. Defaults to false on any error so we never nag
	// the user about a non-confirmed update.
	HasUpdate bool

	// Latest is the tag string from GitHub (e.g. "v0.10.0"). Empty
	// on error.
	Latest string

	// Current is the local build version (Version package var).
	Current string

	// FetchedAt is when we last asked GitHub. Surfaced so the user
	// knows how stale the answer is. UTC.
	FetchedAt time.Time

	// Err is non-nil when the check itself failed (network, parse,
	// rate-limit). Callers display "could not check" instead of
	// pretending no update exists.
	Err error
}

UpdateInfo is the result a caller surfaces in the UI.

func CheckForUpdate added in v0.9.0

func CheckForUpdate(ctx context.Context) UpdateInfo

CheckForUpdate is the entry point. Returns the cached result when fresh; otherwise hits the API, persists, returns. Never blocks longer than the HTTP client's timeout.

Jump to

Keyboard shortcuts

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