mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-07-21 21:31:12 +02:00
* feat(x): first-time-action credit rewards
Reward signed-in free-tier users the first time they connect Gmail, send
an email, take meeting notes, set up a background agent, or build an app.
- core credits service: POST /v1/billing/credit-activations, once per
(user, code); local claimed cache in config/credit_activations.json
keyed by user; 409 reconciles claimed state; other failures retry on
the next occurrence
- triggers at the action success sites in main/core (google oauth
success, gmail:sendReply, meeting:summarize, bg-task create sites,
apps:create); grants broadcast to windows via credits:didActivate
- eligibility: signed-in free tier only (paid starter/pro excluded);
whole feature behind the PostHog credit-rewards flag (default ON,
flag acts as kill switch; ROWBOAT_CREDITS env override for dev)
- UI: sidebar 'Earn $X in credits' pill with checklist popover
(dismissible, rows navigate to each action), settings Account section
with earned state + bonus balance, confetti celebration on grant
- shared: credits catalog/types, credits:getState IPC, BillingInfo
gains store bucket; decodeJwtPayload moved to auth/jwt.ts for reuse
Backend catalog codes deployed separately (rowboatx-backend).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(x): fetch reward catalog from the API, hardcode only activity codes
Review feedback: names, descriptions, and credit amounts are backend-owned
and subject to change; the app now reads them from GET /v1/config
'creditActivations' instead of a hardcoded catalog. Only the activity codes
remain in the app — they anchor the trigger call sites and per-code UI
(icons, navigation).
- shared: drop CREDIT_ACTIVITIES; add CreditActivationCatalogEntrySchema;
RowboatApiConfig gains optional creditActivations
- core: getCreditsState joins the fetched catalog (unknown codes dropped,
API order preserved) with local claimed flags; celebration title comes
from the catalog with the code as fallback
- renderer: description now optional; settings section hides while the
API serves no catalog
Requires the API to serve creditActivations: [{code, displayName,
description?, credits}] on /v1/config; until then the rewards UI stays
hidden and activations still work.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(x): invite-a-friend referral rewards
Surfaces the backend's referral codes (GET /v1/referral, POST
/v1/referral/claims) in the app. The inviter's permanent code appears as
an "Invite friends" item in the sidebar rewards popover and the settings
rewards list, with copy button and claims progress ($5 per friend who
joins, up to 3). The invited side redeems via a self-gating "Have an
invite code?" entry in onboarding's completion step and in settings;
a successful claim fires the existing celebration and refreshes the
balance. Backend error copy (unknown code, own code, already claimed,
cap reached, account too old) is shown inline verbatim.
The one-lifetime-claim state is cached per user in the local claimed
store (pseudo-code referral_claimed), reconciled when the backend
answers "already claimed" from another install. Referral status is
cached for 60s and busted after a claim.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
25 lines
1.1 KiB
TypeScript
25 lines
1.1 KiB
TypeScript
import { PrefixLogger } from './prefix-logger.js';
|
|
|
|
export * as ipc from './ipc.js';
|
|
export * as models from './models.js';
|
|
export * as workspace from './workspace.js';
|
|
export * as mcp from './mcp.js';
|
|
export * as agentSchedule from './agent-schedule.js';
|
|
export * as agentScheduleState from './agent-schedule-state.js';
|
|
export * as serviceEvents from './service-events.js'
|
|
export * as inlineTask from './inline-task.js';
|
|
export * as blocks from './blocks.js';
|
|
export * as liveNote from './live-note.js';
|
|
export * as events from './events.js';
|
|
export * as backgroundTask from './background-task.js';
|
|
export * as promptBlock from './prompt-block.js';
|
|
export * as frontmatter from './frontmatter.js';
|
|
export * as bases from './bases.js';
|
|
export * as browserControl from './browser-control.js';
|
|
export * as billing from './billing.js';
|
|
export * as credits from './credits.js';
|
|
export * as notificationSettings from './notification-settings.js';
|
|
export * as codeSessions from './code-sessions.js';
|
|
export * as channels from './channels.js';
|
|
export * as rowboatApp from './rowboat-app.js';
|
|
export { PrefixLogger };
|