feedback

package
v1.9.1 Latest Latest
Warning

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

Go to latest
Published: May 11, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Index

Constants

View Source
const DiscussionNodeID = "D_kwDOQh82-s4Alt9V"

DiscussionNodeID is the GitHub Discussion node ID for the Feedback Hub. Must be replaced with the real node ID before release. Retrieve after creating the Discussion at:

https://github.com/asheshgoplani/agent-deck/discussions

via: gh api graphql -f query='{ repository(owner:"asheshgoplani",name:"agent-deck") { discussions(first:5) { nodes { id title } } } }'

View Source
const DiscussionURL = "https://github.com/asheshgoplani/agent-deck/discussions"

DiscussionURL is the GitHub Discussions page for agent-deck feedback. Note: GitHub Discussions does NOT support ?body= URL parameter prefill (only GitHub Issues supports this). The browser fallback opens this URL and relies on the user pasting from clipboard into the Discussion form.

Variables

This section is empty.

Functions

func FormatComment

func FormatComment(version string, rating int, goos, goarch, comment string) string

FormatComment formats a feedback submission for posting to GitHub Discussions. Format: "**vVER** | **N/5** EMOJI | GOOS GOARCH\nCOMMENT" When comment is empty, the trailing newline and comment are omitted.

func MinDaysBeforeFirstPrompt added in v1.7.41

func MinDaysBeforeFirstPrompt() int

MinDaysBeforeFirstPrompt returns the configured floor (default 3).

func MinLaunchesBeforeFirstPrompt added in v1.7.41

func MinLaunchesBeforeFirstPrompt() int

MinLaunchesBeforeFirstPrompt returns the configured floor (default 7).

func PromptCooldownDays added in v1.7.41

func PromptCooldownDays() int

PromptCooldownDays returns the configured cooldown (default 14).

func RatingEmoji

func RatingEmoji(rating int) string

RatingEmoji maps a numeric rating (1-5) to an emoji. Returns "" for out-of-range values.

func RecordLaunch added in v1.7.41

func RecordLaunch(s *State, now time.Time)

RecordLaunch increments LaunchCount by 1 and seeds FirstSeenAt with now on the very first call. Subsequent calls never overwrite FirstSeenAt so pacing persists across version upgrades and state reloads. Does NOT save — caller must call SaveState.

func RecordOptOut

func RecordOptOut(s *State)

RecordOptOut sets feedback_enabled to false (permanent opt-out). Does NOT save — caller must call SaveState.

func RecordRating

func RecordRating(s *State, currentVersion string, rating int)

RecordRating sets last_rated_version to currentVersion and resets shown_count to 0. Deliberately does NOT touch FirstSeenAt, LastPromptedAt, or LaunchCount — pacing signals survive a rating so the next version still paces against the user's real history. Does NOT save — caller must call SaveState.

func RecordShown

func RecordShown(s *State, now time.Time)

RecordShown increments shown_count by 1 and stamps LastPromptedAt with now so the cooldown engages for subsequent calls. Does NOT save — caller must call SaveState.

func SaveState

func SaveState(s *State) error

SaveState atomically writes the state to ~/.agent-deck/feedback-state.json. Uses tmp+rename to prevent partial writes (T-01-01).

func ShouldShow

func ShouldShow(s *State, currentVersion string, now time.Time) bool

ShouldShow returns true only when every gate is clear:

  1. feedback_enabled is true
  2. last_rated_version does not match currentVersion
  3. shown_count < max_shows
  4. user has been around for at least MinDaysBeforeFirstPrompt days AND has launched agent-deck at least MinLaunchesBeforeFirstPrompt times
  5. no prompt was shown within the last PromptCooldownDays days

Pure: never mutates state. Callers that want to track first-seen should call RecordLaunch at process start.

Types

type Sender

type Sender struct {
	// GhCmd runs the gh CLI with the given arguments.
	// Real implementation: exec.Command("gh", args...).CombinedOutput().
	GhCmd func(args ...string) error

	// BrowserCmd opens the given URL in the default browser.
	// Real implementation: runtime.GOOS switch (open/xdg-open).
	BrowserCmd func(url string) error

	// ClipboardCmd copies the given text to the system clipboard.
	// Receives the formatted COMMENT BODY (not a URL).
	// Real implementation: clipboard.Copy(text, false).
	ClipboardCmd func(text string) error

	// IsHeadlessFunc returns true when no graphical display is available.
	// Real implementation: platform.IsHeadless().
	IsHeadlessFunc func() bool
}

Sender holds the three-tier send mechanism for feedback submissions. All four function fields are injectable for testing.

func NewSender

func NewSender() *Sender

NewSender returns a *Sender with all four fields populated with real implementations.

func (*Sender) Send

func (s *Sender) Send(version string, rating int, goos, goarch, comment string) error

Send submits feedback using a three-tier fallback chain:

  1. gh CLI via GraphQL mutation (primary)
  2. If gh fails and not headless: copy body to clipboard, then open Discussion URL in browser
  3. If gh fails and headless: copy body to clipboard only (no browser)

version, rating, goos, goarch, comment are used to build the formatted comment body via FormatComment. Send returns nil in all fallback cases — the caller should inform the user that clipboard/browser fallback was used.

type State

type State struct {
	LastRatedVersion string    `json:"last_rated_version"`
	FeedbackEnabled  bool      `json:"feedback_enabled"`
	ShownCount       int       `json:"shown_count"`
	MaxShows         int       `json:"max_shows"`
	LaunchCount      int       `json:"launch_count,omitempty"`
	FirstSeenAt      time.Time `json:"first_seen_at,omitempty"`
	LastPromptedAt   time.Time `json:"last_prompted_at,omitempty"`
}

State holds the persisted feedback preferences for a user. File: ~/.agent-deck/feedback-state.json. Always serializes all fields (D-05).

v1.7.41 added LaunchCount, FirstSeenAt, LastPromptedAt to pace the first prompt for new users. Serialized via RFC3339 through time.Time's MarshalJSON.

func LoadState

func LoadState() (*State, error)

LoadState reads ~/.agent-deck/feedback-state.json and returns the state. If the file does not exist, it returns a default State (FeedbackEnabled=true, MaxShows=3). A missing file is NOT an error. A malformed file returns a default state to prevent crashes.

Jump to

Keyboard shortcuts

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