@prave/shared 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -115,4 +115,27 @@ export declare const recordSkillUsageBatchSchema: z.ZodObject<{
115
115
  }[];
116
116
  }>;
117
117
  export type RecordSkillUsageBatchInput = z.infer<typeof recordSkillUsageBatchSchema>;
118
+ /**
119
+ * Slug-keyed usage event. Used by the real-time PostToolUse hook so the
120
+ * CLI can fire-and-forget without first running `prave sync` to populate
121
+ * `skill_metadata`. The server resolves the slug → `skill_metadata_id`
122
+ * itself, creating a minimal stub row when needed (self-healing).
123
+ */
124
+ export declare const recordSkillUsageBySlugSchema: z.ZodObject<{
125
+ slug: z.ZodString;
126
+ trigger_phrase: z.ZodOptional<z.ZodNullable<z.ZodString>>;
127
+ triggered_at: z.ZodOptional<z.ZodString>;
128
+ agent_type: z.ZodOptional<z.ZodEnum<["claude", "codex", "cursor", "gemini", "cline", "amp"]>>;
129
+ }, "strip", z.ZodTypeAny, {
130
+ slug: string;
131
+ agent_type?: "claude" | "codex" | "cursor" | "gemini" | "cline" | "amp" | undefined;
132
+ trigger_phrase?: string | null | undefined;
133
+ triggered_at?: string | undefined;
134
+ }, {
135
+ slug: string;
136
+ agent_type?: "claude" | "codex" | "cursor" | "gemini" | "cline" | "amp" | undefined;
137
+ trigger_phrase?: string | null | undefined;
138
+ triggered_at?: string | undefined;
139
+ }>;
140
+ export type RecordSkillUsageBySlugInput = z.infer<typeof recordSkillUsageBySlugSchema>;
118
141
  //# sourceMappingURL=intelligence.schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"intelligence.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/intelligence.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,eAAO,MAAM,eAAe,oEAAsB,CAAA;AAElD,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;EAKlC,CAAA;AACF,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAA;AAEvE,eAAO,MAAM,6BAA6B;;;;;;;;;EAGxC,CAAA;AACF,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAA;AAEnF,eAAO,MAAM,oBAAoB;;;;;;;;;EAG/B,CAAA;AACF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA;AAEjE,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;EAYpC,CAAA;AACF,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAA;AAEhF,eAAO,MAAM,sBAAsB;;;;;;;;;EAGjC,CAAA;AACF,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAA;AAE1E;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;EAWtC,CAAA;AACF,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAA"}
1
+ {"version":3,"file":"intelligence.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/intelligence.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,eAAO,MAAM,eAAe,oEAAsB,CAAA;AAElD,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;EAKlC,CAAA;AACF,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAA;AAEvE,eAAO,MAAM,6BAA6B;;;;;;;;;EAGxC,CAAA;AACF,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAA;AAEnF,eAAO,MAAM,oBAAoB;;;;;;;;;EAG/B,CAAA;AACF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA;AAEjE,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;EAYpC,CAAA;AACF,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAA;AAEhF,eAAO,MAAM,sBAAsB;;;;;;;;;EAGjC,CAAA;AACF,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAA;AAE1E;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;EAWtC,CAAA;AACF,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAA;AAEpF;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;EASvC,CAAA;AACF,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAA"}
@@ -47,3 +47,19 @@ export const recordSkillUsageBatchSchema = z.object({
47
47
  .min(1)
48
48
  .max(500),
49
49
  });
50
+ /**
51
+ * Slug-keyed usage event. Used by the real-time PostToolUse hook so the
52
+ * CLI can fire-and-forget without first running `prave sync` to populate
53
+ * `skill_metadata`. The server resolves the slug → `skill_metadata_id`
54
+ * itself, creating a minimal stub row when needed (self-healing).
55
+ */
56
+ export const recordSkillUsageBySlugSchema = z.object({
57
+ slug: z
58
+ .string()
59
+ .min(1)
60
+ .max(120)
61
+ .regex(/^[a-z0-9][a-z0-9_-]*$/i, 'slug must be kebab/snake case'),
62
+ trigger_phrase: z.string().max(500).nullish(),
63
+ triggered_at: z.string().datetime().optional(),
64
+ agent_type: z.enum(['claude', 'codex', 'cursor', 'gemini', 'cline', 'amp']).optional(),
65
+ });
@@ -1,54 +1,113 @@
1
1
  import type { Plan } from '../schemas/billing.schema.js';
2
2
  /**
3
3
  * PLAN_LIMITS — single source of truth for every gate, quota and copy
4
- * choice across the app. Backend uses the numeric/boolean fields to
5
- * enforce rules; frontend reads the same object to render disabled
6
- * states + upgrade CTAs; CLI calls /me/plan and resolves limits here so
7
- * one config drives all three surfaces.
4
+ * choice across the platform.
8
5
  *
9
- * `null` numeric limits = unlimited.
6
+ * Tier identity:
7
+ * - `free` → public **Free** tier. Discovery + 5 installs/month.
8
+ * - `explorer` → marketed as **Pro** ($16/mo · $144/yr). Power-user toolkit.
9
+ * - `creator` → marketed as **Max** ($39/mo · $360/yr). Bulk-dev + BYO-key.
10
+ *
11
+ * The internal IDs stay `free | explorer | creator` because Stripe price
12
+ * env vars, the `profiles.plan` enum and live customer rows already use
13
+ * them — renaming would break every existing reference. The user-visible
14
+ * `label` field is the only thing that ever surfaces in UI copy, and
15
+ * those map cleanly to Free / Pro / Max.
10
16
  */
11
17
  export interface PlanLimits {
12
- /** Display label used in pricing cards / Settings */
18
+ /** Display label used in pricing cards / Settings ("Free" / "Pro" / "Max"). */
13
19
  label: string;
14
- /** Monthly price in EUR (display only — Stripe is the source of truth) */
15
- price_eur_monthly: number;
16
- /** Marketing tagline for the plan card */
20
+ /** Marketing tagline for the plan card. */
17
21
  tagline: string;
18
- /** Marketplace creator share (0–1). Free can't sell. */
19
- creator_revenue_share: number | null;
20
- /** Max public skills the user can publish. null = unlimited. */
21
- max_public_skills: number | null;
22
+ /** Monthly price in USD (display only Stripe is the source of truth). */
23
+ price_usd_monthly: number;
24
+ /** Yearly price in USD ~25-30% off the monthly equivalent. */
25
+ price_usd_yearly: number;
26
+ /** Position on the upgrade ladder. Higher = more features. */
27
+ rank: number;
28
+ /** Highlighted "most popular" pin in the pricing grid. */
29
+ highlight: boolean;
30
+ /** Browse + LLM-search the public registry. Always true. */
31
+ can_discover: boolean;
32
+ /** Bookmarks. Always true. */
33
+ can_bookmark: boolean;
34
+ /**
35
+ * Monthly install ceiling. `null` = unlimited.
36
+ * Free: 5/mo, Pro+ unlimited. Counter resets on calendar month rollover.
37
+ */
38
+ install_monthly_limit: number | null;
39
+ /** Allowed deploy targets. Empty list = no Multi-Agent feature. */
40
+ multi_agent_targets: ReadonlyArray<'claude' | 'codex' | 'cursor' | 'gemini' | 'cline' | 'amp'>;
41
+ /** `prave sync` enabled. */
42
+ can_cli_sync: boolean;
43
+ /** `prave update` (and the dashboard Update Banner). */
44
+ can_cli_update: boolean;
45
+ /** Cross-machine install ledger sync. */
46
+ can_cross_machine_sync: boolean;
47
+ /** Can the user publish public skills? */
48
+ can_authoring_public: boolean;
22
49
  /** Can the user create private skills? */
23
- can_private_skills: boolean;
24
- /** Max private skills if allowed. null = unlimited. */
25
- max_private_skills: number | null;
50
+ can_authoring_private: boolean;
51
+ /**
52
+ * Total authored-skill ceiling (public + private). `null` = unlimited.
53
+ */
54
+ authoring_max_skills: number | null;
26
55
  /** History tab + revert. */
27
56
  can_versioning: boolean;
28
- /** Max paid skills listed simultaneously. 0 = no marketplace. null = unlimited. */
29
- max_marketplace_listings: number | null;
30
- /** Monthly BYOK tester runs. 0 = blocked. null = unlimited. */
31
- tester_credits_monthly: number | null;
32
- /** Max bookmarks. null = unlimited. */
33
- max_bookmarks: number | null;
34
- /** Total skills the user may import via CLI. null = unlimited. */
35
- cli_max_imports: number | null;
36
- /** Monthly export quota via CLI. 0 = blocked. null = unlimited. */
37
- cli_exports_monthly: number | null;
38
- /** `prave sync` enabled. */
39
- can_cli_sync: boolean;
40
- /** Auto-update on `prave sync` rather than diff-only. */
41
- can_cli_auto_update: boolean;
42
- /** `prave install --bulk`, `prave export --bulk`. */
43
- can_cli_bulk: boolean;
44
- /** Drag-and-drop block builder UI. */
45
- can_block_builder: boolean;
46
- /** CI-style skill pipelines + automated tests. */
47
- can_pipelines: boolean;
48
- /** Per-skill analytics page. */
49
- can_analytics: boolean;
50
- /** Verified Creator badge on public profile. */
51
- has_creator_badge: boolean;
57
+ /** AI-Description generate-button in the editor. */
58
+ can_ai_description: boolean;
59
+ /** Pull-request workflow on others' skills. */
60
+ can_pull_requests: boolean;
61
+ /**
62
+ * Monthly Skill-Tester credits. 0 = blocked entirely.
63
+ * 1 run costs `tester_cost_per_run` credits.
64
+ * Free: 0 · Pro: 100 · Max: 300
65
+ */
66
+ tester_credits_monthly: number;
67
+ /** Cost (in credits) of a single tester run. */
68
+ tester_cost_per_run: number;
69
+ /**
70
+ * Anti-spam cooldown between tester runs in seconds. 0 = no cooldown
71
+ * (Max-tier privilege). Pro = 180s (3 min).
72
+ */
73
+ tester_cooldown_seconds: number;
74
+ /** BYO-Anthropic-key tester mode (uses user's own key, no Prave credits). */
75
+ can_byo_tester_key: boolean;
76
+ /** Access the Intelligence dashboard at all. */
77
+ can_intelligence: boolean;
78
+ /**
79
+ * How many of the user's skills get indexed by the Intelligence
80
+ * pipeline (token audit + conflicts + optimizer).
81
+ * Pro = 25, Max = unlimited (`null`). Beyond the limit, skills exist
82
+ * but don't appear in conflict/optimizer outputs.
83
+ */
84
+ intelligence_indexed_max: number | null;
85
+ /** "Apply all suggestions" batch run on the editor. */
86
+ can_apply_all: boolean;
87
+ /** Hook + scanner usage tracking. */
88
+ can_usage_tracking: boolean;
89
+ /**
90
+ * How many days of usage-stat history are retained for the user.
91
+ * `null` = forever.
92
+ */
93
+ usage_history_days: number | null;
94
+ /** CSV export of usage history. */
95
+ can_usage_export: boolean;
96
+ /** Public profile page at `/u/<username>`. */
97
+ can_public_profile: boolean;
98
+ /**
99
+ * Magic-link skill sharing. Generates time-limited URLs that let
100
+ * non-paying recipients install a private skill once. Max-only.
101
+ */
102
+ can_magic_link_share: boolean;
103
+ /** Verified Creator badge (auto for paid plans). */
104
+ has_verified_badge: boolean;
105
+ /** Priority badge highlight (Max only — small visual emphasis). */
106
+ has_priority_badge: boolean;
107
+ /** Priority email support with a 24h SLA. */
108
+ has_priority_support: boolean;
109
+ /** Early access to in-development features. */
110
+ has_early_access: boolean;
52
111
  }
53
112
  export declare const PLAN_LIMITS: Record<Plan, PlanLimits>;
54
113
  export declare const PLAN_RANK: Record<Plan, number>;
@@ -56,7 +115,21 @@ export declare const PLAN_RANK: Record<Plan, number>;
56
115
  export declare const planMeets: (actual: Plan, required: Plan) => boolean;
57
116
  /**
58
117
  * Smallest plan that satisfies a feature flag. Used by the UI to render
59
- * accurate "Upgrade to X" CTAs without hard-coding plan names.
118
+ * accurate "Upgrade to <plan>" CTAs without hard-coding plan names.
119
+ *
120
+ * Numeric features pass when the value is non-zero or `null` (unlimited);
121
+ * boolean features pass when `true`.
60
122
  */
61
123
  export declare const minPlanFor: (feature: keyof PlanLimits) => Plan | null;
124
+ /**
125
+ * Resolve a plan's user-facing label from the internal id. Use this in
126
+ * any copy ("upgrade to Pro", "Max-only feature") so renames stay
127
+ * consistent.
128
+ */
129
+ export declare const planLabel: (plan: Plan) => string;
130
+ /**
131
+ * Compute the user's remaining monthly install allowance. Returns
132
+ * `null` for unlimited tiers and a non-negative number otherwise.
133
+ */
134
+ export declare const installsRemaining: (plan: Plan, usedThisMonth: number) => number | null;
62
135
  //# sourceMappingURL=plan-limits.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"plan-limits.d.ts","sourceRoot":"","sources":["../../src/types/plan-limits.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,8BAA8B,CAAA;AAExD;;;;;;;;GAQG;AACH,MAAM,WAAW,UAAU;IACzB,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAA;IACb,0EAA0E;IAC1E,iBAAiB,EAAE,MAAM,CAAA;IACzB,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAA;IACf,wDAAwD;IACxD,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAA;IAGpC,gEAAgE;IAChE,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,0CAA0C;IAC1C,kBAAkB,EAAE,OAAO,CAAA;IAC3B,uDAAuD;IACvD,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAA;IACjC,4BAA4B;IAC5B,cAAc,EAAE,OAAO,CAAA;IAGvB,mFAAmF;IACnF,wBAAwB,EAAE,MAAM,GAAG,IAAI,CAAA;IAGvC,+DAA+D;IAC/D,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAA;IAGrC,uCAAuC;IACvC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAG5B,kEAAkE;IAClE,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,mEAAmE;IACnE,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,4BAA4B;IAC5B,YAAY,EAAE,OAAO,CAAA;IACrB,yDAAyD;IACzD,mBAAmB,EAAE,OAAO,CAAA;IAC5B,qDAAqD;IACrD,YAAY,EAAE,OAAO,CAAA;IAGrB,sCAAsC;IACtC,iBAAiB,EAAE,OAAO,CAAA;IAC1B,kDAAkD;IAClD,aAAa,EAAE,OAAO,CAAA;IACtB,gCAAgC;IAChC,aAAa,EAAE,OAAO,CAAA;IACtB,gDAAgD;IAChD,iBAAiB,EAAE,OAAO,CAAA;CAC3B;AAED,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,IAAI,EAAE,UAAU,CA+EhD,CAAA;AAED,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAI1C,CAAA;AAED,8DAA8D;AAC9D,eAAO,MAAM,SAAS,GAAI,QAAQ,IAAI,EAAE,UAAU,IAAI,KAAG,OACf,CAAA;AAE1C;;;GAGG;AACH,eAAO,MAAM,UAAU,GAAI,SAAS,MAAM,UAAU,KAAG,IAAI,GAAG,IAO7D,CAAA"}
1
+ {"version":3,"file":"plan-limits.d.ts","sourceRoot":"","sources":["../../src/types/plan-limits.ts"],"names":[],"mappings":"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"}
@@ -1,88 +1,162 @@
1
+ const ALL_AGENTS = ['claude', 'codex', 'cursor', 'gemini', 'cline', 'amp'];
1
2
  export const PLAN_LIMITS = {
3
+ // ── Free ──────────────────────────────────────────────────────────
2
4
  free: {
3
- label: 'Starter',
4
- price_eur_monthly: 0,
5
- tagline: 'Discover, install and try Prave Skills.',
6
- creator_revenue_share: null,
7
- max_public_skills: 3,
8
- can_private_skills: false,
9
- max_private_skills: 0,
10
- can_versioning: false,
11
- max_marketplace_listings: 0,
12
- tester_credits_monthly: 10,
13
- max_bookmarks: 5,
14
- cli_max_imports: 10,
15
- cli_exports_monthly: 0,
5
+ label: 'Free',
6
+ tagline: 'Discover and install Skills across your agents.',
7
+ price_usd_monthly: 0,
8
+ price_usd_yearly: 0,
9
+ rank: 0,
10
+ highlight: false,
11
+ can_discover: true,
12
+ can_bookmark: true,
13
+ install_monthly_limit: 5,
14
+ multi_agent_targets: ['claude'],
16
15
  can_cli_sync: false,
17
- can_cli_auto_update: false,
18
- can_cli_bulk: false,
19
- can_block_builder: false,
20
- can_pipelines: false,
21
- can_analytics: false,
22
- has_creator_badge: false,
16
+ can_cli_update: false,
17
+ can_cross_machine_sync: false,
18
+ can_authoring_public: false,
19
+ can_authoring_private: false,
20
+ authoring_max_skills: 0,
21
+ can_versioning: false,
22
+ can_ai_description: false,
23
+ can_pull_requests: false,
24
+ tester_credits_monthly: 0,
25
+ tester_cost_per_run: 5,
26
+ tester_cooldown_seconds: 0,
27
+ can_byo_tester_key: false,
28
+ can_intelligence: false,
29
+ intelligence_indexed_max: 0,
30
+ can_apply_all: false,
31
+ can_usage_tracking: false,
32
+ usage_history_days: 0,
33
+ can_usage_export: false,
34
+ can_public_profile: false,
35
+ can_magic_link_share: false,
36
+ has_verified_badge: false,
37
+ has_priority_badge: false,
38
+ has_priority_support: false,
39
+ has_early_access: false,
23
40
  },
41
+ // ── Pro (internally `explorer`) ───────────────────────────────────
24
42
  explorer: {
25
- label: 'Explorer',
26
- price_eur_monthly: 4,
27
- tagline: 'For developers building and shipping Skills.',
28
- creator_revenue_share: null,
29
- max_public_skills: 20,
30
- can_private_skills: true,
31
- max_private_skills: 20,
32
- can_versioning: true,
33
- max_marketplace_listings: 0,
34
- tester_credits_monthly: 80,
35
- max_bookmarks: null,
36
- cli_max_imports: null,
37
- cli_exports_monthly: 50,
43
+ label: 'Pro',
44
+ tagline: 'Multi-agent skill ops + Intelligence audit for power users.',
45
+ price_usd_monthly: 16,
46
+ price_usd_yearly: 144,
47
+ rank: 1,
48
+ highlight: true,
49
+ can_discover: true,
50
+ can_bookmark: true,
51
+ install_monthly_limit: null,
52
+ multi_agent_targets: ALL_AGENTS,
38
53
  can_cli_sync: true,
39
- can_cli_auto_update: false,
40
- can_cli_bulk: false,
41
- can_block_builder: false,
42
- can_pipelines: false,
43
- can_analytics: false,
44
- has_creator_badge: false,
54
+ can_cli_update: true,
55
+ can_cross_machine_sync: true,
56
+ can_authoring_public: true,
57
+ can_authoring_private: true,
58
+ authoring_max_skills: null,
59
+ can_versioning: true,
60
+ can_ai_description: true,
61
+ can_pull_requests: true,
62
+ tester_credits_monthly: 100,
63
+ tester_cost_per_run: 5,
64
+ tester_cooldown_seconds: 180,
65
+ can_byo_tester_key: false,
66
+ can_intelligence: true,
67
+ intelligence_indexed_max: 25,
68
+ can_apply_all: false,
69
+ can_usage_tracking: true,
70
+ usage_history_days: 30,
71
+ can_usage_export: false,
72
+ can_public_profile: true,
73
+ can_magic_link_share: false,
74
+ has_verified_badge: true,
75
+ has_priority_badge: false,
76
+ has_priority_support: false,
77
+ has_early_access: false,
45
78
  },
79
+ // ── Max (internally `creator`) ────────────────────────────────────
46
80
  creator: {
47
- label: 'Creator',
48
- price_eur_monthly: 10,
49
- tagline: 'For power users shipping and selling Skills daily.',
50
- creator_revenue_share: 0.7,
51
- max_public_skills: null,
52
- can_private_skills: true,
53
- max_private_skills: null,
54
- can_versioning: true,
55
- max_marketplace_listings: null,
56
- tester_credits_monthly: 250,
57
- max_bookmarks: null,
58
- cli_max_imports: null,
59
- cli_exports_monthly: null,
81
+ label: 'Max',
82
+ tagline: 'Bulk-dev tier with unlimited audit, BYO-key tester and magic-link sharing.',
83
+ price_usd_monthly: 39,
84
+ price_usd_yearly: 360,
85
+ rank: 2,
86
+ highlight: false,
87
+ can_discover: true,
88
+ can_bookmark: true,
89
+ install_monthly_limit: null,
90
+ multi_agent_targets: ALL_AGENTS,
60
91
  can_cli_sync: true,
61
- can_cli_auto_update: true,
62
- can_cli_bulk: true,
63
- can_block_builder: true,
64
- can_pipelines: true,
65
- can_analytics: true,
66
- has_creator_badge: true,
92
+ can_cli_update: true,
93
+ can_cross_machine_sync: true,
94
+ can_authoring_public: true,
95
+ can_authoring_private: true,
96
+ authoring_max_skills: null,
97
+ can_versioning: true,
98
+ can_ai_description: true,
99
+ can_pull_requests: true,
100
+ tester_credits_monthly: 300,
101
+ tester_cost_per_run: 5,
102
+ tester_cooldown_seconds: 0,
103
+ can_byo_tester_key: true,
104
+ can_intelligence: true,
105
+ intelligence_indexed_max: null,
106
+ can_apply_all: true,
107
+ can_usage_tracking: true,
108
+ usage_history_days: null,
109
+ can_usage_export: true,
110
+ can_public_profile: true,
111
+ can_magic_link_share: true,
112
+ has_verified_badge: true,
113
+ has_priority_badge: true,
114
+ has_priority_support: true,
115
+ has_early_access: true,
67
116
  },
68
117
  };
69
118
  export const PLAN_RANK = {
70
- free: 0,
71
- explorer: 1,
72
- creator: 2,
119
+ free: PLAN_LIMITS.free.rank,
120
+ explorer: PLAN_LIMITS.explorer.rank,
121
+ creator: PLAN_LIMITS.creator.rank,
73
122
  };
74
123
  /** True when `actual` includes everything `required` does. */
75
124
  export const planMeets = (actual, required) => PLAN_RANK[actual] >= PLAN_RANK[required];
76
125
  /**
77
126
  * Smallest plan that satisfies a feature flag. Used by the UI to render
78
- * accurate "Upgrade to X" CTAs without hard-coding plan names.
127
+ * accurate "Upgrade to <plan>" CTAs without hard-coding plan names.
128
+ *
129
+ * Numeric features pass when the value is non-zero or `null` (unlimited);
130
+ * boolean features pass when `true`.
79
131
  */
80
132
  export const minPlanFor = (feature) => {
81
133
  const order = ['free', 'explorer', 'creator'];
82
134
  for (const plan of order) {
83
135
  const v = PLAN_LIMITS[plan][feature];
84
- if (typeof v === 'boolean' ? v : v !== 0)
136
+ if (typeof v === 'boolean' && v)
137
+ return plan;
138
+ if (typeof v === 'number' && v > 0)
139
+ return plan;
140
+ if (v === null)
141
+ return plan;
142
+ if (Array.isArray(v) && v.length > 0)
85
143
  return plan;
86
144
  }
87
145
  return null;
88
146
  };
147
+ /**
148
+ * Resolve a plan's user-facing label from the internal id. Use this in
149
+ * any copy ("upgrade to Pro", "Max-only feature") so renames stay
150
+ * consistent.
151
+ */
152
+ export const planLabel = (plan) => PLAN_LIMITS[plan].label;
153
+ /**
154
+ * Compute the user's remaining monthly install allowance. Returns
155
+ * `null` for unlimited tiers and a non-negative number otherwise.
156
+ */
157
+ export const installsRemaining = (plan, usedThisMonth) => {
158
+ const limit = PLAN_LIMITS[plan].install_monthly_limit;
159
+ if (limit === null)
160
+ return null;
161
+ return Math.max(0, limit - usedThisMonth);
162
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prave/shared",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"