@cullit/core 1.9.2 → 1.10.1
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 +4 -3
- package/dist/index.js +21 -15
- package/package.json +10 -3
package/dist/index.d.ts
CHANGED
|
@@ -71,7 +71,7 @@ interface PipelineResult {
|
|
|
71
71
|
duration: number;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
declare const VERSION = "1.
|
|
74
|
+
declare const VERSION = "1.10.1";
|
|
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", "openclaw", "none"];
|
|
@@ -159,6 +159,7 @@ declare function registerFormatter(format: string, fn: FormatterFn): void;
|
|
|
159
159
|
declare function getFormatter(format: string): FormatterFn | undefined;
|
|
160
160
|
declare function listFormatters(): string[];
|
|
161
161
|
declare function formatNotes(notes: ReleaseNotes, format: OutputFormat): string;
|
|
162
|
+
declare function escapeHtml(str: string): string;
|
|
162
163
|
|
|
163
164
|
/**
|
|
164
165
|
* Outputs release notes to stdout (default).
|
|
@@ -281,7 +282,7 @@ declare function reportUsage(project?: string): Promise<void>;
|
|
|
281
282
|
* Core registers: git collector, template generator, stdout/file publishers.
|
|
282
283
|
* Pro registers: AI generator, Jira/Linear collectors + enrichers, Slack/Discord/GitHub publishers.
|
|
283
284
|
*
|
|
284
|
-
*
|
|
285
|
+
* Paid plugin registration is preloaded by the licensed distribution package.
|
|
285
286
|
*/
|
|
286
287
|
|
|
287
288
|
type CollectorFactory = (...args: any[]) => Collector;
|
|
@@ -321,4 +322,4 @@ declare function runPipeline(from: string, to: string, config: CullConfig, optio
|
|
|
321
322
|
templateProfile?: string;
|
|
322
323
|
}): Promise<PipelineResult>;
|
|
323
324
|
|
|
324
|
-
export { AI_PROVIDERS, AUDIENCES, CHANGE_CATEGORIES, type ChangeCategory, type ChangeEntry, type Collector, type CollectorFactory, 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, PUBLISHER_TYPES, type PipelineResult, type Publisher, type PublisherFactory, type ReleaseAdvisory, type ReleaseNotes, SOURCE_TYPES, type SemverBump, StdoutPublisher, TONES, type TeamFeature, TemplateGenerator, type UsageLimits, VERSION, analyzeReleaseReadiness, createLogger, fetchWithTimeout, formatNotes, getCollector, getEnricher, getFeatureGating, getFormatter, getGenerator, getLatestTag, getPublisher, getRecentTags, getTierLimits, hasCollector, hasEnricher, hasGenerator, hasPublisher, isEnrichmentAllowed, isFeatureAllowed, isProviderAllowed, isPublisherAllowed, listCollectors, listEnrichers, listFormatters, listGenerators, listPublishers, registerCollector, registerEnricher, registerFormatter, registerGenerator, registerPublisher, reportUsage, resolveLicense, runPipeline, upgradeMessage, validateLicense };
|
|
325
|
+
export { AI_PROVIDERS, AUDIENCES, CHANGE_CATEGORIES, type ChangeCategory, type ChangeEntry, type Collector, type CollectorFactory, 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, PUBLISHER_TYPES, type PipelineResult, type Publisher, type PublisherFactory, type ReleaseAdvisory, type ReleaseNotes, SOURCE_TYPES, type SemverBump, StdoutPublisher, TONES, type TeamFeature, TemplateGenerator, type UsageLimits, VERSION, analyzeReleaseReadiness, createLogger, escapeHtml, fetchWithTimeout, formatNotes, getCollector, getEnricher, getFeatureGating, getFormatter, getGenerator, getLatestTag, getPublisher, getRecentTags, getTierLimits, hasCollector, hasEnricher, hasGenerator, hasPublisher, isEnrichmentAllowed, isFeatureAllowed, 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 = "1.
|
|
2
|
+
var VERSION = "1.10.1";
|
|
3
3
|
var DEFAULT_CATEGORIES = ["features", "fixes", "breaking", "improvements", "chores"];
|
|
4
4
|
var DEFAULT_MODELS = {
|
|
5
5
|
anthropic: "claude-sonnet-4-20250514",
|
|
@@ -72,7 +72,8 @@ var GitCollector = class {
|
|
|
72
72
|
{ cwd: this.cwd, encoding: "utf-8", maxBuffer: 10 * 1024 * 1024 }
|
|
73
73
|
);
|
|
74
74
|
} catch (error) {
|
|
75
|
-
const
|
|
75
|
+
const errWithStderr = typeof error === "object" && error !== null && "stderr" in error ? error : void 0;
|
|
76
|
+
const stderr = errWithStderr?.stderr?.toString?.() || "";
|
|
76
77
|
const hint = stderr.includes("unknown revision") ? 'Check that both refs exist (run "cullit tags" to see tags).' : stderr.includes("not a git repository") ? "Run this command inside a git repository." : `Make sure both refs exist and you're in a git repository.`;
|
|
77
78
|
throw new Error(
|
|
78
79
|
`Failed to read git log between ${from} and ${to}. ${hint}`
|
|
@@ -280,9 +281,10 @@ var TemplateGenerator = class {
|
|
|
280
281
|
const categoryOrder = ["breaking", "features", "improvements", "fixes", "chores", "other"];
|
|
281
282
|
deduped.sort((a, b) => categoryOrder.indexOf(a.category) - categoryOrder.indexOf(b.category));
|
|
282
283
|
const contributors = [...new Set(diff.commits.map((c) => c.author))];
|
|
284
|
+
const tagDate = diff.commits.length > 0 ? new Date(diff.commits[0].date).toISOString().split("T")[0] : (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
283
285
|
return {
|
|
284
286
|
version: diff.to,
|
|
285
|
-
date:
|
|
287
|
+
date: tagDate,
|
|
286
288
|
summary: this.buildSummary(deduped, diff.commits.length, config.tone),
|
|
287
289
|
changes: deduped.slice(0, 20),
|
|
288
290
|
contributors,
|
|
@@ -417,15 +419,15 @@ function formatNotes(notes, format) {
|
|
|
417
419
|
const fn = formatters.get(format) || formatters.get("markdown");
|
|
418
420
|
return fn(notes);
|
|
419
421
|
}
|
|
420
|
-
function
|
|
422
|
+
function sanitizeForMarkdown(text) {
|
|
421
423
|
return escapeHtml(text).replace(/\r?\n/g, " ");
|
|
422
424
|
}
|
|
423
425
|
function formatMarkdown(notes) {
|
|
424
426
|
const lines = [];
|
|
425
|
-
lines.push(`## ${
|
|
427
|
+
lines.push(`## ${sanitizeForMarkdown(notes.version)} \u2014 ${sanitizeForMarkdown(notes.date)}`);
|
|
426
428
|
lines.push("");
|
|
427
429
|
if (notes.summary) {
|
|
428
|
-
lines.push(
|
|
430
|
+
lines.push(sanitizeForMarkdown(notes.summary));
|
|
429
431
|
lines.push("");
|
|
430
432
|
}
|
|
431
433
|
const grouped = groupByCategory(notes);
|
|
@@ -435,8 +437,8 @@ function formatMarkdown(notes) {
|
|
|
435
437
|
lines.push(`### ${CATEGORY_LABELS[category]}`);
|
|
436
438
|
lines.push("");
|
|
437
439
|
for (const entry of entries) {
|
|
438
|
-
let line = `- ${
|
|
439
|
-
if (entry.ticketKey) line += ` (${
|
|
440
|
+
let line = `- ${sanitizeForMarkdown(entry.description)}`;
|
|
441
|
+
if (entry.ticketKey) line += ` (${sanitizeForMarkdown(entry.ticketKey)})`;
|
|
440
442
|
lines.push(line);
|
|
441
443
|
}
|
|
442
444
|
lines.push("");
|
|
@@ -444,7 +446,7 @@ function formatMarkdown(notes) {
|
|
|
444
446
|
if (notes.contributors?.length) {
|
|
445
447
|
lines.push("### Contributors");
|
|
446
448
|
lines.push("");
|
|
447
|
-
lines.push(notes.contributors.map((c) => `@${
|
|
449
|
+
lines.push(notes.contributors.map((c) => `@${sanitizeForMarkdown(c)}`).join(", "));
|
|
448
450
|
lines.push("");
|
|
449
451
|
}
|
|
450
452
|
if (notes.metadata) {
|
|
@@ -772,7 +774,7 @@ async function validateLicense() {
|
|
|
772
774
|
if (cachedValidation && cachedValidation.key === key) {
|
|
773
775
|
return cachedValidation.status;
|
|
774
776
|
}
|
|
775
|
-
return { tier: "
|
|
777
|
+
return { tier: "free", valid: true, message: "License validation unavailable offline. Run while connected to activate your Pro license." };
|
|
776
778
|
}
|
|
777
779
|
}
|
|
778
780
|
function isProviderAllowed(provider, license) {
|
|
@@ -977,7 +979,10 @@ async function runPipeline(from, to, config, options = {}) {
|
|
|
977
979
|
const log = options.logger || createLogger("normal");
|
|
978
980
|
const license = await validateLicense();
|
|
979
981
|
if (!license.valid) {
|
|
980
|
-
|
|
982
|
+
if (!isProviderAllowed(config.ai.provider, license)) {
|
|
983
|
+
throw new Error(license.message || "Invalid CULLIT_API_KEY");
|
|
984
|
+
}
|
|
985
|
+
log.warn(`\u26A0 ${license.message || "Invalid CULLIT_API_KEY \u2014 running in free mode."}`);
|
|
981
986
|
}
|
|
982
987
|
if (!isProviderAllowed(config.ai.provider, license)) {
|
|
983
988
|
throw new Error(upgradeMessage(`AI provider "${config.ai.provider}"`));
|
|
@@ -985,7 +990,7 @@ async function runPipeline(from, to, config, options = {}) {
|
|
|
985
990
|
const collectorFactory = getCollector(config.source.type);
|
|
986
991
|
if (!collectorFactory) {
|
|
987
992
|
throw new Error(
|
|
988
|
-
`Source type "${config.source.type}" is not available. ` + (config.source.type !== "local" ? "Install @cullit/
|
|
993
|
+
`Source type "${config.source.type}" is not available. ` + (config.source.type !== "local" ? "Install @cullit/licensed (private distribution) to use this source." : "Valid sources: local")
|
|
989
994
|
);
|
|
990
995
|
}
|
|
991
996
|
const sourceLabel = config.source.type === "local" ? `commits between ${from}..${to}` : `items from ${config.source.type}`;
|
|
@@ -1007,7 +1012,7 @@ async function runPipeline(from, to, config, options = {}) {
|
|
|
1007
1012
|
}
|
|
1008
1013
|
const enricherFactory = getEnricher(source);
|
|
1009
1014
|
if (!enricherFactory) {
|
|
1010
|
-
log.info(`\xBB Skipping ${source} enrichment \u2014 install @cullit/
|
|
1015
|
+
log.info(`\xBB Skipping ${source} enrichment \u2014 install @cullit/licensed to enable`);
|
|
1011
1016
|
continue;
|
|
1012
1017
|
}
|
|
1013
1018
|
log.info(`\xBB Enriching from ${source}...`);
|
|
@@ -1031,7 +1036,7 @@ async function runPipeline(from, to, config, options = {}) {
|
|
|
1031
1036
|
const generatorFactory = getGenerator(config.ai.provider);
|
|
1032
1037
|
if (!generatorFactory) {
|
|
1033
1038
|
throw new Error(
|
|
1034
|
-
`AI provider "${config.ai.provider}" is not available. ` + (config.ai.provider !== "none" ? "Install @cullit/
|
|
1039
|
+
`AI provider "${config.ai.provider}" is not available. ` + (config.ai.provider !== "none" ? "Install @cullit/licensed (private distribution) to use AI providers." : "")
|
|
1035
1040
|
);
|
|
1036
1041
|
}
|
|
1037
1042
|
let generator;
|
|
@@ -1061,7 +1066,7 @@ async function runPipeline(from, to, config, options = {}) {
|
|
|
1061
1066
|
}
|
|
1062
1067
|
const publisherFactory = getPublisher(target.type);
|
|
1063
1068
|
if (!publisherFactory) {
|
|
1064
|
-
log.info(`\xBB Skipping ${target.type} \u2014 install @cullit/
|
|
1069
|
+
log.info(`\xBB Skipping ${target.type} \u2014 install @cullit/licensed to enable`);
|
|
1065
1070
|
continue;
|
|
1066
1071
|
}
|
|
1067
1072
|
const publisher = publisherFactory(target);
|
|
@@ -1129,6 +1134,7 @@ export {
|
|
|
1129
1134
|
VERSION,
|
|
1130
1135
|
analyzeReleaseReadiness,
|
|
1131
1136
|
createLogger,
|
|
1137
|
+
escapeHtml,
|
|
1132
1138
|
fetchWithTimeout,
|
|
1133
1139
|
formatNotes,
|
|
1134
1140
|
getCollector,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cullit/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Core engine for Cullit — AI-powered release note generation.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -16,6 +16,10 @@
|
|
|
16
16
|
"ai",
|
|
17
17
|
"automation"
|
|
18
18
|
],
|
|
19
|
+
"homepage": "https://cullit.io",
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/mttaylor/cullit/issues"
|
|
22
|
+
},
|
|
19
23
|
"main": "./dist/index.js",
|
|
20
24
|
"types": "./dist/index.d.ts",
|
|
21
25
|
"exports": {
|
|
@@ -28,10 +32,13 @@
|
|
|
28
32
|
"dist"
|
|
29
33
|
],
|
|
30
34
|
"engines": {
|
|
31
|
-
"node": ">=
|
|
35
|
+
"node": ">=22"
|
|
36
|
+
},
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
32
39
|
},
|
|
33
40
|
"dependencies": {
|
|
34
|
-
"@cullit/config": "1.
|
|
41
|
+
"@cullit/config": "1.10.1"
|
|
35
42
|
},
|
|
36
43
|
"scripts": {
|
|
37
44
|
"build": "tsup src/index.ts --format esm --dts --clean",
|