@cullit/core 0.4.0 → 1.0.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 +43 -5
- package/dist/index.js +152 -70
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EnrichmentType, OutputFormat, AIConfig, CullConfig } from '@cullit/config';
|
|
2
|
-
export { AIConfig, AIProvider, Audience, CullConfig, EnrichmentType, JiraConfig, LinearConfig, OpenClawConfig, OutputFormat, PublishTarget, PublisherType, SourceConfig, Tone } from '@cullit/config';
|
|
2
|
+
export { AIConfig, AIProvider, Audience, BitbucketConfig, ConfluenceConfig, CullConfig, EnrichmentType, GitLabConfig, JiraConfig, LinearConfig, NotionConfig, OpenClawConfig, OutputFormat, PublishTarget, PublisherType, SourceConfig, Tone } from '@cullit/config';
|
|
3
3
|
|
|
4
4
|
interface GitCommit {
|
|
5
5
|
hash: string;
|
|
@@ -31,7 +31,7 @@ interface EnrichedContext {
|
|
|
31
31
|
diff: GitDiff;
|
|
32
32
|
tickets: EnrichedTicket[];
|
|
33
33
|
}
|
|
34
|
-
type ChangeCategory =
|
|
34
|
+
type ChangeCategory = string;
|
|
35
35
|
interface ChangeEntry {
|
|
36
36
|
description: string;
|
|
37
37
|
category: ChangeCategory;
|
|
@@ -71,9 +71,17 @@ interface PipelineResult {
|
|
|
71
71
|
duration: number;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
declare const VERSION = "0.
|
|
74
|
+
declare const VERSION = "1.0.0";
|
|
75
75
|
declare const DEFAULT_CATEGORIES: string[];
|
|
76
76
|
declare const DEFAULT_MODELS: Record<string, string>;
|
|
77
|
+
declare const AI_PROVIDERS: readonly ["anthropic", "openai", "gemini", "ollama", "openclaw", "none"];
|
|
78
|
+
declare const OUTPUT_FORMATS: readonly ["markdown", "html", "json"];
|
|
79
|
+
declare const PUBLISHER_TYPES: readonly ["stdout", "file", "slack", "discord", "github-release", "teams", "confluence", "notion", "gitlab-release", "changelog"];
|
|
80
|
+
declare const ENRICHMENT_TYPES: readonly ["jira", "linear"];
|
|
81
|
+
declare const CHANGE_CATEGORIES: readonly ["features", "fixes", "breaking", "improvements", "chores", "other"];
|
|
82
|
+
declare const AUDIENCES: readonly ["developer", "end-user", "executive"];
|
|
83
|
+
declare const TONES: readonly ["professional", "casual", "terse"];
|
|
84
|
+
declare const SOURCE_TYPES: readonly ["local", "jira", "linear", "gitlab", "bitbucket"];
|
|
77
85
|
|
|
78
86
|
type LogLevel = 'quiet' | 'normal' | 'verbose';
|
|
79
87
|
interface Logger {
|
|
@@ -129,6 +137,10 @@ declare class TemplateGenerator implements Generator {
|
|
|
129
137
|
private buildSummary;
|
|
130
138
|
}
|
|
131
139
|
|
|
140
|
+
type FormatterFn = (notes: ReleaseNotes) => string;
|
|
141
|
+
declare function registerFormatter(format: string, fn: FormatterFn): void;
|
|
142
|
+
declare function getFormatter(format: string): FormatterFn | undefined;
|
|
143
|
+
declare function listFormatters(): string[];
|
|
132
144
|
declare function formatNotes(notes: ReleaseNotes, format: OutputFormat): string;
|
|
133
145
|
|
|
134
146
|
/**
|
|
@@ -185,6 +197,9 @@ declare function analyzeReleaseReadiness(cwd?: string): ReleaseAdvisory;
|
|
|
185
197
|
*
|
|
186
198
|
* Free tier (no key): provider=none, publish to stdout/file only
|
|
187
199
|
* Pro tier (with key): all providers, all publishers, all enrichments
|
|
200
|
+
*
|
|
201
|
+
* validateLicense() performs async remote validation with caching.
|
|
202
|
+
* resolveLicense() remains sync for quick format-only checks (display).
|
|
188
203
|
*/
|
|
189
204
|
type LicenseTier = 'free' | 'pro';
|
|
190
205
|
interface LicenseStatus {
|
|
@@ -194,9 +209,15 @@ interface LicenseStatus {
|
|
|
194
209
|
}
|
|
195
210
|
/**
|
|
196
211
|
* Resolve the user's license tier from CULLIT_API_KEY env var.
|
|
197
|
-
*
|
|
212
|
+
* Sync format-only check — use for display, not enforcement.
|
|
198
213
|
*/
|
|
199
214
|
declare function resolveLicense(): LicenseStatus;
|
|
215
|
+
/**
|
|
216
|
+
* Validate the license asynchronously with remote server validation.
|
|
217
|
+
* Falls back to format-only check if offline or no validation URL configured.
|
|
218
|
+
* Results are cached for 24 hours per key.
|
|
219
|
+
*/
|
|
220
|
+
declare function validateLicense(): Promise<LicenseStatus>;
|
|
200
221
|
/**
|
|
201
222
|
* Check whether the current license allows the requested provider.
|
|
202
223
|
*/
|
|
@@ -213,6 +234,19 @@ declare function isEnrichmentAllowed(license: LicenseStatus): boolean;
|
|
|
213
234
|
* Build a human-readable upgrade message for a gated feature.
|
|
214
235
|
*/
|
|
215
236
|
declare function upgradeMessage(feature: string): string;
|
|
237
|
+
interface UsageLimits {
|
|
238
|
+
generationsPerMonth: number;
|
|
239
|
+
maxProjects: number;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Get usage limits for a license tier.
|
|
243
|
+
*/
|
|
244
|
+
declare function getTierLimits(tier: string): UsageLimits;
|
|
245
|
+
/**
|
|
246
|
+
* Report a generation event to the metering service.
|
|
247
|
+
* Non-blocking — failures are logged but never block the pipeline.
|
|
248
|
+
*/
|
|
249
|
+
declare function reportUsage(project?: string): Promise<void>;
|
|
216
250
|
|
|
217
251
|
/**
|
|
218
252
|
* Plugin Registry — the seam between free (core) and pro features.
|
|
@@ -239,6 +273,10 @@ declare function hasGenerator(provider: string): boolean;
|
|
|
239
273
|
declare function hasCollector(type: string): boolean;
|
|
240
274
|
declare function hasPublisher(type: string): boolean;
|
|
241
275
|
declare function hasEnricher(type: string): boolean;
|
|
276
|
+
declare function listCollectors(): string[];
|
|
277
|
+
declare function listEnrichers(): string[];
|
|
278
|
+
declare function listGenerators(): string[];
|
|
279
|
+
declare function listPublishers(): string[];
|
|
242
280
|
|
|
243
281
|
/**
|
|
244
282
|
* Shared fetch wrapper with timeout support.
|
|
@@ -255,4 +293,4 @@ declare function runPipeline(from: string, to: string, config: CullConfig, optio
|
|
|
255
293
|
logger?: Logger;
|
|
256
294
|
}): Promise<PipelineResult>;
|
|
257
295
|
|
|
258
|
-
export { type ChangeCategory, type ChangeEntry, type Collector, type CollectorFactory, DEFAULT_CATEGORIES, DEFAULT_MODELS, 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, type PipelineResult, type Publisher, type PublisherFactory, type ReleaseAdvisory, type ReleaseNotes, type SemverBump, StdoutPublisher, TemplateGenerator, VERSION, analyzeReleaseReadiness, createLogger, fetchWithTimeout, formatNotes, getCollector, getEnricher, getGenerator, getLatestTag, getPublisher, getRecentTags, hasCollector, hasEnricher, hasGenerator, hasPublisher, isEnrichmentAllowed, isProviderAllowed, isPublisherAllowed, registerCollector, registerEnricher, registerGenerator, registerPublisher, resolveLicense, runPipeline, upgradeMessage };
|
|
296
|
+
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, OUTPUT_FORMATS, PUBLISHER_TYPES, type PipelineResult, type Publisher, type PublisherFactory, type ReleaseAdvisory, type ReleaseNotes, SOURCE_TYPES, type SemverBump, StdoutPublisher, TONES, TemplateGenerator, type UsageLimits, VERSION, analyzeReleaseReadiness, createLogger, fetchWithTimeout, formatNotes, getCollector, getEnricher, getFormatter, getGenerator, getLatestTag, getPublisher, getRecentTags, getTierLimits, hasCollector, hasEnricher, hasGenerator, hasPublisher, isEnrichmentAllowed, 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 = "0.
|
|
2
|
+
var VERSION = "1.0.0";
|
|
3
3
|
var DEFAULT_CATEGORIES = ["features", "fixes", "breaking", "improvements", "chores"];
|
|
4
4
|
var DEFAULT_MODELS = {
|
|
5
5
|
anthropic: "claude-sonnet-4-20250514",
|
|
@@ -8,6 +8,14 @@ var DEFAULT_MODELS = {
|
|
|
8
8
|
ollama: "llama3.1",
|
|
9
9
|
openclaw: "anthropic/claude-sonnet-4-6"
|
|
10
10
|
};
|
|
11
|
+
var AI_PROVIDERS = ["anthropic", "openai", "gemini", "ollama", "openclaw", "none"];
|
|
12
|
+
var OUTPUT_FORMATS = ["markdown", "html", "json"];
|
|
13
|
+
var PUBLISHER_TYPES = ["stdout", "file", "slack", "discord", "github-release", "teams", "confluence", "notion", "gitlab-release", "changelog"];
|
|
14
|
+
var ENRICHMENT_TYPES = ["jira", "linear"];
|
|
15
|
+
var CHANGE_CATEGORIES = ["features", "fixes", "breaking", "improvements", "chores", "other"];
|
|
16
|
+
var AUDIENCES = ["developer", "end-user", "executive"];
|
|
17
|
+
var TONES = ["professional", "casual", "terse"];
|
|
18
|
+
var SOURCE_TYPES = ["local", "jira", "linear", "gitlab", "bitbucket"];
|
|
11
19
|
|
|
12
20
|
// src/logger.ts
|
|
13
21
|
function createLogger(level = "normal") {
|
|
@@ -289,6 +297,16 @@ var TemplateGenerator = class {
|
|
|
289
297
|
};
|
|
290
298
|
|
|
291
299
|
// src/formatter.ts
|
|
300
|
+
var formatters = /* @__PURE__ */ new Map();
|
|
301
|
+
function registerFormatter(format, fn) {
|
|
302
|
+
formatters.set(format, fn);
|
|
303
|
+
}
|
|
304
|
+
function getFormatter(format) {
|
|
305
|
+
return formatters.get(format);
|
|
306
|
+
}
|
|
307
|
+
function listFormatters() {
|
|
308
|
+
return Array.from(formatters.keys());
|
|
309
|
+
}
|
|
292
310
|
var CATEGORY_LABELS = {
|
|
293
311
|
features: "\u2728 Features",
|
|
294
312
|
fixes: "\u{1F41B} Bug Fixes",
|
|
@@ -306,16 +324,8 @@ var CATEGORY_ORDER = [
|
|
|
306
324
|
"other"
|
|
307
325
|
];
|
|
308
326
|
function formatNotes(notes, format) {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
return formatMarkdown(notes);
|
|
312
|
-
case "html":
|
|
313
|
-
return formatHTML(notes);
|
|
314
|
-
case "json":
|
|
315
|
-
return JSON.stringify(notes, null, 2);
|
|
316
|
-
default:
|
|
317
|
-
return formatMarkdown(notes);
|
|
318
|
-
}
|
|
327
|
+
const fn = formatters.get(format) || formatters.get("markdown");
|
|
328
|
+
return fn(notes);
|
|
319
329
|
}
|
|
320
330
|
function formatMarkdown(notes) {
|
|
321
331
|
const lines = [];
|
|
@@ -386,6 +396,9 @@ function groupByCategory(notes) {
|
|
|
386
396
|
}
|
|
387
397
|
return grouped;
|
|
388
398
|
}
|
|
399
|
+
registerFormatter("markdown", formatMarkdown);
|
|
400
|
+
registerFormatter("html", formatHTML);
|
|
401
|
+
registerFormatter("json", (notes) => JSON.stringify(notes, null, 2));
|
|
389
402
|
|
|
390
403
|
// src/publishers/index.ts
|
|
391
404
|
import { writeFileSync } from "fs";
|
|
@@ -531,9 +544,28 @@ function analyzeReleaseReadiness(cwd = process.cwd()) {
|
|
|
531
544
|
};
|
|
532
545
|
}
|
|
533
546
|
|
|
547
|
+
// src/fetch.ts
|
|
548
|
+
var DEFAULT_TIMEOUT = 3e4;
|
|
549
|
+
async function fetchWithTimeout(url, init, timeoutMs = DEFAULT_TIMEOUT) {
|
|
550
|
+
const controller = new AbortController();
|
|
551
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
552
|
+
try {
|
|
553
|
+
return await fetch(url, { ...init, signal: controller.signal });
|
|
554
|
+
} catch (err) {
|
|
555
|
+
if (err.name === "AbortError") {
|
|
556
|
+
throw new Error(`Request to ${new URL(url).hostname} timed out after ${timeoutMs / 1e3}s`);
|
|
557
|
+
}
|
|
558
|
+
throw err;
|
|
559
|
+
} finally {
|
|
560
|
+
clearTimeout(timer);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
534
564
|
// src/gate.ts
|
|
535
565
|
var FREE_PROVIDERS = /* @__PURE__ */ new Set(["none"]);
|
|
536
566
|
var FREE_PUBLISHERS = /* @__PURE__ */ new Set(["stdout", "file"]);
|
|
567
|
+
var LICENSE_CACHE_TTL = 24 * 60 * 60 * 1e3;
|
|
568
|
+
var cachedValidation = null;
|
|
537
569
|
function resolveLicense() {
|
|
538
570
|
const key = process.env.CULLIT_API_KEY?.trim();
|
|
539
571
|
if (!key) {
|
|
@@ -544,6 +576,48 @@ function resolveLicense() {
|
|
|
544
576
|
}
|
|
545
577
|
return { tier: "pro", valid: true };
|
|
546
578
|
}
|
|
579
|
+
async function validateLicense() {
|
|
580
|
+
const key = process.env.CULLIT_API_KEY?.trim();
|
|
581
|
+
const validationUrl = process.env.CULLIT_LICENSE_URL?.trim();
|
|
582
|
+
if (!key) {
|
|
583
|
+
return { tier: "free", valid: true };
|
|
584
|
+
}
|
|
585
|
+
if (!/^clt_[a-zA-Z0-9]{32,}$/.test(key)) {
|
|
586
|
+
return { tier: "free", valid: false, message: "Invalid CULLIT_API_KEY format. Expected: clt_<key>" };
|
|
587
|
+
}
|
|
588
|
+
if (cachedValidation && cachedValidation.key === key && Date.now() < cachedValidation.expiresAt) {
|
|
589
|
+
return cachedValidation.status;
|
|
590
|
+
}
|
|
591
|
+
if (!validationUrl) {
|
|
592
|
+
return { tier: "pro", valid: true };
|
|
593
|
+
}
|
|
594
|
+
try {
|
|
595
|
+
const res = await fetchWithTimeout(validationUrl, {
|
|
596
|
+
method: "POST",
|
|
597
|
+
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${key}` },
|
|
598
|
+
body: JSON.stringify({ key })
|
|
599
|
+
}, 1e4);
|
|
600
|
+
if (res.ok) {
|
|
601
|
+
const data = await res.json();
|
|
602
|
+
const status2 = {
|
|
603
|
+
tier: data.tier === "pro" ? "pro" : "free",
|
|
604
|
+
valid: data.valid !== false,
|
|
605
|
+
message: data.message
|
|
606
|
+
};
|
|
607
|
+
cachedValidation = { status: status2, key, expiresAt: Date.now() + LICENSE_CACHE_TTL };
|
|
608
|
+
return status2;
|
|
609
|
+
}
|
|
610
|
+
const status = {
|
|
611
|
+
tier: "free",
|
|
612
|
+
valid: false,
|
|
613
|
+
message: "License validation failed. Check your API key at https://cullit.io/pricing"
|
|
614
|
+
};
|
|
615
|
+
cachedValidation = { status, key, expiresAt: Date.now() + LICENSE_CACHE_TTL };
|
|
616
|
+
return status;
|
|
617
|
+
} catch {
|
|
618
|
+
return { tier: "pro", valid: true };
|
|
619
|
+
}
|
|
620
|
+
}
|
|
547
621
|
function isProviderAllowed(provider, license) {
|
|
548
622
|
if (license.tier === "pro" && license.valid) return true;
|
|
549
623
|
return FREE_PROVIDERS.has(provider);
|
|
@@ -560,6 +634,35 @@ function upgradeMessage(feature) {
|
|
|
560
634
|
Get your API key at https://cullit.io/pricing
|
|
561
635
|
Then set CULLIT_API_KEY in your environment.`;
|
|
562
636
|
}
|
|
637
|
+
var TIER_LIMITS = {
|
|
638
|
+
free: { generationsPerMonth: 10, maxProjects: 1 },
|
|
639
|
+
pro: { generationsPerMonth: 500, maxProjects: 5 },
|
|
640
|
+
team: { generationsPerMonth: 2e3, maxProjects: 25 },
|
|
641
|
+
enterprise: { generationsPerMonth: Infinity, maxProjects: Infinity }
|
|
642
|
+
};
|
|
643
|
+
function getTierLimits(tier) {
|
|
644
|
+
return TIER_LIMITS[tier] || TIER_LIMITS.free;
|
|
645
|
+
}
|
|
646
|
+
async function reportUsage(project = "default") {
|
|
647
|
+
const key = process.env.CULLIT_API_KEY?.trim();
|
|
648
|
+
const meterUrl = process.env.CULLIT_METER_URL?.trim();
|
|
649
|
+
if (!meterUrl || !key) return;
|
|
650
|
+
try {
|
|
651
|
+
await fetchWithTimeout(meterUrl, {
|
|
652
|
+
method: "POST",
|
|
653
|
+
headers: {
|
|
654
|
+
"Content-Type": "application/json",
|
|
655
|
+
"Authorization": `Bearer ${key}`
|
|
656
|
+
},
|
|
657
|
+
body: JSON.stringify({
|
|
658
|
+
event: "generation",
|
|
659
|
+
project,
|
|
660
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
661
|
+
})
|
|
662
|
+
}, 5e3);
|
|
663
|
+
} catch {
|
|
664
|
+
}
|
|
665
|
+
}
|
|
563
666
|
|
|
564
667
|
// src/registry.ts
|
|
565
668
|
var collectors = /* @__PURE__ */ new Map();
|
|
@@ -602,34 +705,29 @@ function hasPublisher(type) {
|
|
|
602
705
|
function hasEnricher(type) {
|
|
603
706
|
return enrichers.has(type);
|
|
604
707
|
}
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
}
|
|
617
|
-
throw err;
|
|
618
|
-
} finally {
|
|
619
|
-
clearTimeout(timer);
|
|
620
|
-
}
|
|
708
|
+
function listCollectors() {
|
|
709
|
+
return Array.from(collectors.keys());
|
|
710
|
+
}
|
|
711
|
+
function listEnrichers() {
|
|
712
|
+
return Array.from(enrichers.keys());
|
|
713
|
+
}
|
|
714
|
+
function listGenerators() {
|
|
715
|
+
return Array.from(generators.keys());
|
|
716
|
+
}
|
|
717
|
+
function listPublishers() {
|
|
718
|
+
return Array.from(publishers.keys());
|
|
621
719
|
}
|
|
622
720
|
|
|
623
721
|
// src/index.ts
|
|
624
722
|
registerCollector("local", () => new GitCollector());
|
|
625
723
|
registerGenerator("none", () => new TemplateGenerator());
|
|
626
|
-
registerPublisher("stdout", () => new StdoutPublisher());
|
|
627
|
-
registerPublisher("file", (
|
|
724
|
+
registerPublisher("stdout", (_target) => new StdoutPublisher());
|
|
725
|
+
registerPublisher("file", (target) => new FilePublisher(target.path));
|
|
628
726
|
async function runPipeline(from, to, config, options = {}) {
|
|
629
727
|
const startTime = Date.now();
|
|
630
728
|
const format = options.format || "markdown";
|
|
631
729
|
const log = options.logger || createLogger("normal");
|
|
632
|
-
const license =
|
|
730
|
+
const license = await validateLicense();
|
|
633
731
|
if (!license.valid) {
|
|
634
732
|
throw new Error(license.message || "Invalid CULLIT_API_KEY");
|
|
635
733
|
}
|
|
@@ -639,20 +737,12 @@ async function runPipeline(from, to, config, options = {}) {
|
|
|
639
737
|
const collectorFactory = getCollector(config.source.type);
|
|
640
738
|
if (!collectorFactory) {
|
|
641
739
|
throw new Error(
|
|
642
|
-
`Source type "${config.source.type}" is not available. ` + (config.source.type
|
|
740
|
+
`Source type "${config.source.type}" is not available. ` + (config.source.type !== "local" ? "Install @cullit/pro to use this source." : "Valid sources: local")
|
|
643
741
|
);
|
|
644
742
|
}
|
|
645
|
-
const sourceLabel = config.source.type === "
|
|
743
|
+
const sourceLabel = config.source.type === "local" ? `commits between ${from}..${to}` : `items from ${config.source.type}`;
|
|
646
744
|
log.info(`\xBB Collecting ${sourceLabel}`);
|
|
647
|
-
|
|
648
|
-
if (config.source.type === "jira") {
|
|
649
|
-
if (!config.jira) throw new Error("Jira source requires jira config in .cullit.yml");
|
|
650
|
-
collector = collectorFactory(config.jira);
|
|
651
|
-
} else if (config.source.type === "linear") {
|
|
652
|
-
collector = collectorFactory(config.linear?.apiKey);
|
|
653
|
-
} else {
|
|
654
|
-
collector = collectorFactory();
|
|
655
|
-
}
|
|
745
|
+
const collector = collectorFactory(config);
|
|
656
746
|
const diff = await collector.collect(from, to);
|
|
657
747
|
const itemLabel = config.source.type === "jira" || config.source.type === "linear" ? "issues" : "commits";
|
|
658
748
|
log.info(`\xBB Found ${diff.commits.length} ${itemLabel}${diff.filesChanged ? `, ${diff.filesChanged} files changed` : ""}`);
|
|
@@ -673,14 +763,7 @@ async function runPipeline(from, to, config, options = {}) {
|
|
|
673
763
|
continue;
|
|
674
764
|
}
|
|
675
765
|
log.info(`\xBB Enriching from ${source}...`);
|
|
676
|
-
|
|
677
|
-
if (source === "jira" && config.jira) {
|
|
678
|
-
enricher = enricherFactory(config.jira);
|
|
679
|
-
} else if (source === "linear") {
|
|
680
|
-
enricher = enricherFactory(config.linear?.apiKey);
|
|
681
|
-
} else {
|
|
682
|
-
continue;
|
|
683
|
-
}
|
|
766
|
+
const enricher = enricherFactory(config);
|
|
684
767
|
const enrichedTickets = await enricher.enrich(diff);
|
|
685
768
|
tickets.push(...enrichedTickets);
|
|
686
769
|
log.info(`\xBB ${source}: found ${enrichedTickets.length} ${source === "jira" ? "tickets" : "issues"}`);
|
|
@@ -725,26 +808,7 @@ async function runPipeline(from, to, config, options = {}) {
|
|
|
725
808
|
log.info(`\xBB Skipping ${target.type} \u2014 install @cullit/pro to enable`);
|
|
726
809
|
continue;
|
|
727
810
|
}
|
|
728
|
-
|
|
729
|
-
switch (target.type) {
|
|
730
|
-
case "stdout":
|
|
731
|
-
publisher = publisherFactory();
|
|
732
|
-
break;
|
|
733
|
-
case "file":
|
|
734
|
-
if (!target.path) continue;
|
|
735
|
-
publisher = publisherFactory(target.path);
|
|
736
|
-
break;
|
|
737
|
-
case "slack":
|
|
738
|
-
case "discord":
|
|
739
|
-
if (!target.webhookUrl) continue;
|
|
740
|
-
publisher = publisherFactory(target.webhookUrl);
|
|
741
|
-
break;
|
|
742
|
-
case "github-release":
|
|
743
|
-
publisher = publisherFactory();
|
|
744
|
-
break;
|
|
745
|
-
default:
|
|
746
|
-
continue;
|
|
747
|
-
}
|
|
811
|
+
const publisher = publisherFactory(target);
|
|
748
812
|
await publisher.publish(notes, format, formatted);
|
|
749
813
|
publishedTo.push(target.type === "file" ? `file:${target.path}` : target.type);
|
|
750
814
|
} catch (err) {
|
|
@@ -762,11 +826,19 @@ async function runPipeline(from, to, config, options = {}) {
|
|
|
762
826
|
return { notes, formatted, publishedTo, duration };
|
|
763
827
|
}
|
|
764
828
|
export {
|
|
829
|
+
AI_PROVIDERS,
|
|
830
|
+
AUDIENCES,
|
|
831
|
+
CHANGE_CATEGORIES,
|
|
765
832
|
DEFAULT_CATEGORIES,
|
|
766
833
|
DEFAULT_MODELS,
|
|
834
|
+
ENRICHMENT_TYPES,
|
|
767
835
|
FilePublisher,
|
|
768
836
|
GitCollector,
|
|
837
|
+
OUTPUT_FORMATS,
|
|
838
|
+
PUBLISHER_TYPES,
|
|
839
|
+
SOURCE_TYPES,
|
|
769
840
|
StdoutPublisher,
|
|
841
|
+
TONES,
|
|
770
842
|
TemplateGenerator,
|
|
771
843
|
VERSION,
|
|
772
844
|
analyzeReleaseReadiness,
|
|
@@ -775,10 +847,12 @@ export {
|
|
|
775
847
|
formatNotes,
|
|
776
848
|
getCollector,
|
|
777
849
|
getEnricher,
|
|
850
|
+
getFormatter,
|
|
778
851
|
getGenerator,
|
|
779
852
|
getLatestTag,
|
|
780
853
|
getPublisher,
|
|
781
854
|
getRecentTags,
|
|
855
|
+
getTierLimits,
|
|
782
856
|
hasCollector,
|
|
783
857
|
hasEnricher,
|
|
784
858
|
hasGenerator,
|
|
@@ -786,11 +860,19 @@ export {
|
|
|
786
860
|
isEnrichmentAllowed,
|
|
787
861
|
isProviderAllowed,
|
|
788
862
|
isPublisherAllowed,
|
|
863
|
+
listCollectors,
|
|
864
|
+
listEnrichers,
|
|
865
|
+
listFormatters,
|
|
866
|
+
listGenerators,
|
|
867
|
+
listPublishers,
|
|
789
868
|
registerCollector,
|
|
790
869
|
registerEnricher,
|
|
870
|
+
registerFormatter,
|
|
791
871
|
registerGenerator,
|
|
792
872
|
registerPublisher,
|
|
873
|
+
reportUsage,
|
|
793
874
|
resolveLicense,
|
|
794
875
|
runPipeline,
|
|
795
|
-
upgradeMessage
|
|
876
|
+
upgradeMessage,
|
|
877
|
+
validateLicense
|
|
796
878
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cullit/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Core engine for Cullit — AI-powered release note generation.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"node": ">=18"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@cullit/config": "0.
|
|
34
|
+
"@cullit/config": "1.0.0"
|
|
35
35
|
},
|
|
36
36
|
"scripts": {
|
|
37
37
|
"build": "tsup src/index.ts --format esm --dts --clean",
|