Documentation
¶
Index ¶
- Constants
- func FormatComment(version string, rating int, goos, goarch, comment string) string
- func MinDaysBeforeFirstPrompt() int
- func MinLaunchesBeforeFirstPrompt() int
- func PromptCooldownDays() int
- func RatingEmoji(rating int) string
- func RecordLaunch(s *State, now time.Time)
- func RecordOptOut(s *State)
- func RecordRating(s *State, currentVersion string, rating int)
- func RecordShown(s *State, now time.Time)
- func SaveState(s *State) error
- func ShouldShow(s *State, currentVersion string, now time.Time) bool
- type Sender
- type State
Constants ¶
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 } } } }'
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 ¶
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 ¶
RatingEmoji maps a numeric rating (1-5) to an emoji. Returns "" for out-of-range values.
func RecordLaunch ¶ added in v1.7.41
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 ¶
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 ¶
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 ¶
SaveState atomically writes the state to ~/.agent-deck/feedback-state.json. Uses tmp+rename to prevent partial writes (T-01-01).
func ShouldShow ¶
ShouldShow returns true only when every gate is clear:
- feedback_enabled is true
- last_rated_version does not match currentVersion
- shown_count < max_shows
- user has been around for at least MinDaysBeforeFirstPrompt days AND has launched agent-deck at least MinLaunchesBeforeFirstPrompt times
- 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 ¶
Send submits feedback using a three-tier fallback chain:
- gh CLI via GraphQL mutation (primary)
- If gh fails and not headless: copy body to clipboard, then open Discussion URL in browser
- 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.