@prave/shared 1.0.1 → 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.
- package/dist/schemas/intelligence.schema.d.ts +23 -0
- package/dist/schemas/intelligence.schema.d.ts.map +1 -1
- package/dist/schemas/intelligence.schema.js +16 -0
- package/dist/types/plan-limits.d.ts +114 -41
- package/dist/types/plan-limits.d.ts.map +1 -1
- package/dist/types/plan-limits.js +136 -62
- package/package.json +1 -1
|
@@ -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
|
|
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
|
-
*
|
|
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
|
-
/**
|
|
15
|
-
price_eur_monthly: number;
|
|
16
|
-
/** Marketing tagline for the plan card */
|
|
20
|
+
/** Marketing tagline for the plan card. */
|
|
17
21
|
tagline: string;
|
|
18
|
-
/**
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
|
|
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
|
-
|
|
24
|
-
/**
|
|
25
|
-
|
|
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
|
-
/**
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
|
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
|
|
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: '
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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: '
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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: '
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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:
|
|
71
|
-
explorer:
|
|
72
|
-
creator:
|
|
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
|
|
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'
|
|
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
|
+
};
|