@cullit/core 2.0.6 → 2.1.0
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/index.d.ts +22 -7
- package/dist/index.js +39 -12
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -71,7 +71,7 @@ interface PipelineResult {
|
|
|
71
71
|
duration: number;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
declare const VERSION = "2.0
|
|
74
|
+
declare const VERSION = "2.1.0";
|
|
75
75
|
declare const DEFAULT_CATEGORIES: string[];
|
|
76
76
|
declare const DEFAULT_MODELS: Record<string, string>;
|
|
77
77
|
declare const AI_PROVIDERS: readonly ["anthropic", "openai", "gemini", "ollama", "none"];
|
|
@@ -82,8 +82,8 @@ declare const CHANGE_CATEGORIES: readonly ["features", "fixes", "breaking", "imp
|
|
|
82
82
|
declare const AUDIENCES: readonly ["developer", "end-user", "executive"];
|
|
83
83
|
declare const TONES: readonly ["professional", "casual", "terse", "edgy", "hype", "snarky"];
|
|
84
84
|
declare const SOURCE_TYPES: readonly ["local", "jira", "linear", "gitlab", "bitbucket", "multi-repo"];
|
|
85
|
-
declare const TIERS: readonly ["free", "
|
|
86
|
-
declare const PAID_TIERS: readonly ["
|
|
85
|
+
declare const TIERS: readonly ["free", "pro", "team", "enterprise"];
|
|
86
|
+
declare const PAID_TIERS: readonly ["pro", "team", "enterprise"];
|
|
87
87
|
declare const TEAM_TIERS: readonly ["team", "enterprise"];
|
|
88
88
|
declare const TEAM_PLANS: readonly ["team-5", "team-10", "team-25"];
|
|
89
89
|
type TeamPlan = (typeof TEAM_PLANS)[number];
|
|
@@ -219,13 +219,16 @@ declare function analyzeReleaseReadiness(cwd?: string): ReleaseAdvisory;
|
|
|
219
219
|
/**
|
|
220
220
|
* Cullit License Gating
|
|
221
221
|
*
|
|
222
|
-
* Free tier (no key):
|
|
223
|
-
* Pro tier (with key): all providers, all publishers,
|
|
222
|
+
* Free tier (no key): 3 AI gens/month, all providers (BYOK), publish to stdout/file only
|
|
223
|
+
* Pro tier (with key): 500 gens/month, all providers, all publishers, enrichments, audience/tone
|
|
224
|
+
* Team tier: 2000 gens/month, team management, advanced publishers
|
|
225
|
+
* Team 25: 5000 gens/month, 500 projects, branded widget, project templates, audit logs
|
|
226
|
+
* Enterprise tier: unlimited everything
|
|
224
227
|
*
|
|
225
228
|
* validateLicense() performs async remote validation with caching.
|
|
226
229
|
* resolveLicense() remains sync for quick format-only checks (display).
|
|
227
230
|
*/
|
|
228
|
-
type LicenseTier = 'free' | '
|
|
231
|
+
type LicenseTier = 'free' | 'pro' | 'team' | 'enterprise';
|
|
229
232
|
interface LicenseStatus {
|
|
230
233
|
tier: LicenseTier;
|
|
231
234
|
valid: boolean;
|
|
@@ -244,6 +247,7 @@ declare function resolveLicense(): LicenseStatus;
|
|
|
244
247
|
declare function validateLicense(): Promise<LicenseStatus>;
|
|
245
248
|
/**
|
|
246
249
|
* Check whether the current license allows the requested provider.
|
|
250
|
+
* All tiers now allow AI providers (BYOK) — enforcement is via generation limits.
|
|
247
251
|
*/
|
|
248
252
|
declare function isProviderAllowed(provider: string, license: LicenseStatus): boolean;
|
|
249
253
|
/**
|
|
@@ -275,11 +279,22 @@ interface UsageLimits {
|
|
|
275
279
|
* Get usage limits for a license tier.
|
|
276
280
|
*/
|
|
277
281
|
declare function getTierLimits(tier: string): UsageLimits;
|
|
282
|
+
/**
|
|
283
|
+
* Get usage limits for a specific plan, falling back to tier defaults.
|
|
284
|
+
* Use when the plan is known (API context); use getTierLimits when only tier is known (CLI).
|
|
285
|
+
*/
|
|
286
|
+
declare function getPlanLimits(plan: string, tier: string): UsageLimits;
|
|
278
287
|
type TeamFeature = 'drafts' | 'approvals' | 'shared_history' | 'project_templates' | 'hosted_changelog' | 'branded_widget' | 'team_publishers' | 'org_settings' | 'audit_logs' | 'sso';
|
|
279
288
|
/**
|
|
280
289
|
* Check whether a license tier grants access to a Team/Enterprise feature.
|
|
281
290
|
*/
|
|
282
291
|
declare function isFeatureAllowed(feature: TeamFeature, tier: string, valid?: boolean): boolean;
|
|
292
|
+
/**
|
|
293
|
+
* Check whether a specific plan grants access to a feature.
|
|
294
|
+
* Use when the plan is known (API context); enterprise always passes.
|
|
295
|
+
* Falls back to tier-level check for features without plan restrictions.
|
|
296
|
+
*/
|
|
297
|
+
declare function isPlanFeatureAllowed(feature: TeamFeature, plan: string, tier: string, valid?: boolean): boolean;
|
|
283
298
|
/**
|
|
284
299
|
* Build a gating summary for a tier — which features are unlocked.
|
|
285
300
|
*/
|
|
@@ -396,4 +411,4 @@ declare function runPipeline(from: string, to: string, config: CullConfig, optio
|
|
|
396
411
|
templateProfile?: string;
|
|
397
412
|
}): Promise<PipelineResult>;
|
|
398
413
|
|
|
399
|
-
export { AI_PROVIDERS, AUDIENCES, CHANGE_CATEGORIES, type ChangeCategory, type ChangeEntry, type Collector, type CollectorFactory, CoreErrorCode, type CoreErrorCodeValue, CullitError, DEFAULT_CATEGORIES, DEFAULT_MODELS, ENRICHMENT_TYPES, type EnrichedContext, type EnrichedTicket, type Enricher, type EnricherFactory, FilePublisher, type Generator, type GeneratorFactory, GitCollector, type GitCommit, type GitDiff, type LicenseStatus, type LicenseTier, type LogLevel, type Logger, MultiRepoCollector, OUTPUT_FORMATS, PAID_TIERS, PUBLISHER_TYPES, type PipelineResult, type Publisher, type PublisherFactory, type RateLimitResult, type RateLimiter, type RateLimiterOptions, type ReleaseAdvisory, type ReleaseNotes, SOURCE_TYPES, type SemverBump, StdoutPublisher, TEAM_PLANS, TEAM_PLAN_SEATS, TEAM_TIERS, TIERS, TONES, type TeamFeature, type TeamPlan, TemplateGenerator, type UsageLimits, VERSION, analyzeReleaseReadiness, createLogger, createRateLimiter, escapeHtml, fetchWithTimeout, formatNotes, getCollector, getEnricher, getFeatureGating, getFormatter, getGenerator, getLatestTag, getPublisher, getRecentTags, getTierLimits, hasCollector, hasEnricher, hasGenerator, hasPublisher, isAudienceToneAllowed, isEnrichmentAllowed, isFeatureAllowed, isProviderAllowed, isPublisherAllowed, listCollectors, listEnrichers, listFormatters, listGenerators, listPublishers, registerCollector, registerEnricher, registerFormatter, registerGenerator, registerPublisher, reportUsage, resolveLicense, runPipeline, upgradeMessage, validateLicense };
|
|
414
|
+
export { AI_PROVIDERS, AUDIENCES, CHANGE_CATEGORIES, type ChangeCategory, type ChangeEntry, type Collector, type CollectorFactory, CoreErrorCode, type CoreErrorCodeValue, CullitError, DEFAULT_CATEGORIES, DEFAULT_MODELS, ENRICHMENT_TYPES, type EnrichedContext, type EnrichedTicket, type Enricher, type EnricherFactory, FilePublisher, type Generator, type GeneratorFactory, GitCollector, type GitCommit, type GitDiff, type LicenseStatus, type LicenseTier, type LogLevel, type Logger, MultiRepoCollector, OUTPUT_FORMATS, PAID_TIERS, PUBLISHER_TYPES, type PipelineResult, type Publisher, type PublisherFactory, type RateLimitResult, type RateLimiter, type RateLimiterOptions, type ReleaseAdvisory, type ReleaseNotes, SOURCE_TYPES, type SemverBump, StdoutPublisher, TEAM_PLANS, TEAM_PLAN_SEATS, TEAM_TIERS, TIERS, TONES, type TeamFeature, type TeamPlan, TemplateGenerator, type UsageLimits, VERSION, analyzeReleaseReadiness, createLogger, createRateLimiter, escapeHtml, fetchWithTimeout, formatNotes, getCollector, getEnricher, getFeatureGating, getFormatter, getGenerator, getLatestTag, getPlanLimits, getPublisher, getRecentTags, getTierLimits, hasCollector, hasEnricher, hasGenerator, hasPublisher, isAudienceToneAllowed, isEnrichmentAllowed, isFeatureAllowed, isPlanFeatureAllowed, isProviderAllowed, isPublisherAllowed, listCollectors, listEnrichers, listFormatters, listGenerators, listPublishers, registerCollector, registerEnricher, registerFormatter, registerGenerator, registerPublisher, reportUsage, resolveLicense, runPipeline, upgradeMessage, validateLicense };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/constants.ts
|
|
2
|
-
var VERSION = "2.0
|
|
2
|
+
var VERSION = "2.1.0";
|
|
3
3
|
var DEFAULT_CATEGORIES = ["features", "fixes", "breaking", "improvements", "chores"];
|
|
4
4
|
var DEFAULT_MODELS = {
|
|
5
5
|
anthropic: "claude-sonnet-4-20250514",
|
|
@@ -15,8 +15,8 @@ var CHANGE_CATEGORIES = ["features", "fixes", "breaking", "improvements", "chore
|
|
|
15
15
|
var AUDIENCES = ["developer", "end-user", "executive"];
|
|
16
16
|
var TONES = ["professional", "casual", "terse", "edgy", "hype", "snarky"];
|
|
17
17
|
var SOURCE_TYPES = ["local", "jira", "linear", "gitlab", "bitbucket", "multi-repo"];
|
|
18
|
-
var TIERS = ["free", "
|
|
19
|
-
var PAID_TIERS = ["
|
|
18
|
+
var TIERS = ["free", "pro", "team", "enterprise"];
|
|
19
|
+
var PAID_TIERS = ["pro", "team", "enterprise"];
|
|
20
20
|
var TEAM_TIERS = ["team", "enterprise"];
|
|
21
21
|
var TEAM_PLANS = ["team-5", "team-10", "team-25"];
|
|
22
22
|
var TEAM_PLAN_SEATS = {
|
|
@@ -757,7 +757,6 @@ async function fetchWithTimeout(url, init, timeoutMs = DEFAULT_TIMEOUT) {
|
|
|
757
757
|
}
|
|
758
758
|
|
|
759
759
|
// src/gate.ts
|
|
760
|
-
var FREE_PROVIDERS = /* @__PURE__ */ new Set(["none"]);
|
|
761
760
|
var FREE_PUBLISHERS = /* @__PURE__ */ new Set(["stdout", "file"]);
|
|
762
761
|
var TEAM_ONLY_PUBLISHERS = /* @__PURE__ */ new Set(["confluence", "notion", "teams"]);
|
|
763
762
|
var LICENSE_CACHE_TTL = 24 * 60 * 60 * 1e3;
|
|
@@ -809,7 +808,7 @@ async function validateLicense() {
|
|
|
809
808
|
if (res.ok) {
|
|
810
809
|
const data = await res.json();
|
|
811
810
|
const status2 = {
|
|
812
|
-
tier: data.tier === "team" || data.tier === "enterprise" ? data.tier : data.tier === "pro" ? "pro" :
|
|
811
|
+
tier: data.tier === "team" || data.tier === "enterprise" ? data.tier : data.tier === "pro" ? "pro" : "free",
|
|
813
812
|
valid: data.valid !== false,
|
|
814
813
|
message: data.message
|
|
815
814
|
};
|
|
@@ -831,8 +830,8 @@ async function validateLicense() {
|
|
|
831
830
|
}
|
|
832
831
|
}
|
|
833
832
|
function isProviderAllowed(provider, license) {
|
|
834
|
-
if (license.
|
|
835
|
-
return
|
|
833
|
+
if (!license.valid) return provider === "none";
|
|
834
|
+
return true;
|
|
836
835
|
}
|
|
837
836
|
function isPublisherAllowed(publisherType, license) {
|
|
838
837
|
if (TEAM_ONLY_PUBLISHERS.has(publisherType)) {
|
|
@@ -848,38 +847,59 @@ function isAudienceToneAllowed(license) {
|
|
|
848
847
|
return (license.tier === "pro" || license.tier === "team" || license.tier === "enterprise") && license.valid;
|
|
849
848
|
}
|
|
850
849
|
function upgradeMessage(feature, minTier) {
|
|
851
|
-
const tierLabel = minTier === "team" ? "a Team plan or above" : minTier === "pro" ? "a Pro plan or above" : minTier === "
|
|
850
|
+
const tierLabel = minTier === "team" ? "a Team plan or above" : minTier === "pro" ? "a Pro plan or above" : minTier === "enterprise" ? "an Enterprise plan" : "a paid Cullit plan";
|
|
852
851
|
return `\u{1F512} ${feature} requires ${tierLabel}.
|
|
853
852
|
Upgrade at https://cullit.io/pricing
|
|
854
853
|
Then set CULLIT_API_KEY in your environment.`;
|
|
855
854
|
}
|
|
856
855
|
var TIER_LIMITS = {
|
|
857
|
-
free: { generationsPerMonth:
|
|
858
|
-
basic: { generationsPerMonth: 50, maxProjects: 10 },
|
|
856
|
+
free: { generationsPerMonth: 3, maxProjects: 3 },
|
|
859
857
|
pro: { generationsPerMonth: 500, maxProjects: 100 },
|
|
860
858
|
team: { generationsPerMonth: 2e3, maxProjects: 250 },
|
|
861
859
|
enterprise: { generationsPerMonth: Infinity, maxProjects: Infinity }
|
|
862
860
|
};
|
|
861
|
+
var PLAN_LIMITS = {
|
|
862
|
+
"team-25": { generationsPerMonth: 5e3, maxProjects: 500 }
|
|
863
|
+
};
|
|
863
864
|
function getTierLimits(tier) {
|
|
864
865
|
return TIER_LIMITS[tier] || TIER_LIMITS.free;
|
|
865
866
|
}
|
|
867
|
+
function getPlanLimits(plan, tier) {
|
|
868
|
+
return PLAN_LIMITS[plan] || TIER_LIMITS[tier] || TIER_LIMITS.free;
|
|
869
|
+
}
|
|
866
870
|
var FEATURE_TIERS = {
|
|
867
871
|
drafts: /* @__PURE__ */ new Set(["team", "enterprise"]),
|
|
868
872
|
approvals: /* @__PURE__ */ new Set(["team", "enterprise"]),
|
|
869
873
|
shared_history: /* @__PURE__ */ new Set(["team", "enterprise"]),
|
|
870
|
-
project_templates: /* @__PURE__ */ new Set(["
|
|
874
|
+
project_templates: /* @__PURE__ */ new Set(["enterprise"]),
|
|
875
|
+
// plan-gated: team-25 via PLAN_FEATURES
|
|
871
876
|
hosted_changelog: /* @__PURE__ */ new Set(["pro", "team", "enterprise"]),
|
|
872
|
-
branded_widget: /* @__PURE__ */ new Set(["
|
|
877
|
+
branded_widget: /* @__PURE__ */ new Set(["enterprise"]),
|
|
878
|
+
// plan-gated: team-25 via PLAN_FEATURES
|
|
873
879
|
team_publishers: /* @__PURE__ */ new Set(["team", "enterprise"]),
|
|
874
880
|
org_settings: /* @__PURE__ */ new Set(["team", "enterprise"]),
|
|
875
881
|
audit_logs: /* @__PURE__ */ new Set(["enterprise"]),
|
|
882
|
+
// plan-gated: team-25 via PLAN_FEATURES
|
|
876
883
|
sso: /* @__PURE__ */ new Set(["enterprise"])
|
|
877
884
|
};
|
|
885
|
+
var PLAN_FEATURES = {
|
|
886
|
+
branded_widget: /* @__PURE__ */ new Set(["team-25"]),
|
|
887
|
+
project_templates: /* @__PURE__ */ new Set(["team-25"]),
|
|
888
|
+
audit_logs: /* @__PURE__ */ new Set(["team-25"])
|
|
889
|
+
};
|
|
878
890
|
function isFeatureAllowed(feature, tier, valid = true) {
|
|
879
891
|
if (!valid) return false;
|
|
880
892
|
const allowed = FEATURE_TIERS[feature];
|
|
881
893
|
return allowed ? allowed.has(tier) : false;
|
|
882
894
|
}
|
|
895
|
+
function isPlanFeatureAllowed(feature, plan, tier, valid = true) {
|
|
896
|
+
if (!valid) return false;
|
|
897
|
+
if (tier === "enterprise") return true;
|
|
898
|
+
const planSet = PLAN_FEATURES[feature];
|
|
899
|
+
if (planSet) return planSet.has(plan);
|
|
900
|
+
const tierSet = FEATURE_TIERS[feature];
|
|
901
|
+
return tierSet ? tierSet.has(tier) : false;
|
|
902
|
+
}
|
|
883
903
|
function getFeatureGating(tier) {
|
|
884
904
|
const result = {};
|
|
885
905
|
for (const feature of Object.keys(FEATURE_TIERS)) {
|
|
@@ -1182,6 +1202,11 @@ async function runPipeline(from, to, config, options = {}) {
|
|
|
1182
1202
|
}
|
|
1183
1203
|
}
|
|
1184
1204
|
const context = { diff, tickets };
|
|
1205
|
+
const hasCustomAudience = config.ai.audience && config.ai.audience !== "developer";
|
|
1206
|
+
const hasCustomTone = config.ai.tone && config.ai.tone !== "professional";
|
|
1207
|
+
if ((hasCustomAudience || hasCustomTone) && !isAudienceToneAllowed(license)) {
|
|
1208
|
+
throw new CullitError(CoreErrorCode.LICENSE_TIER_INSUFFICIENT, upgradeMessage("Audience and tone control", "pro"));
|
|
1209
|
+
}
|
|
1185
1210
|
const providerNames = {
|
|
1186
1211
|
anthropic: "Claude",
|
|
1187
1212
|
openai: "OpenAI",
|
|
@@ -1306,6 +1331,7 @@ export {
|
|
|
1306
1331
|
getFormatter,
|
|
1307
1332
|
getGenerator,
|
|
1308
1333
|
getLatestTag,
|
|
1334
|
+
getPlanLimits,
|
|
1309
1335
|
getPublisher,
|
|
1310
1336
|
getRecentTags,
|
|
1311
1337
|
getTierLimits,
|
|
@@ -1316,6 +1342,7 @@ export {
|
|
|
1316
1342
|
isAudienceToneAllowed,
|
|
1317
1343
|
isEnrichmentAllowed,
|
|
1318
1344
|
isFeatureAllowed,
|
|
1345
|
+
isPlanFeatureAllowed,
|
|
1319
1346
|
isProviderAllowed,
|
|
1320
1347
|
isPublisherAllowed,
|
|
1321
1348
|
listCollectors,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cullit/core",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Core engine for Cullit — AI-powered release note generation.",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"access": "public"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@cullit/config": "2.0
|
|
41
|
+
"@cullit/config": "2.1.0"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"build": "tsup src/index.ts --format esm --dts --clean",
|