@releasekit/notes 0.2.0-next.9 → 0.2.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/LICENSE +21 -0
- package/README.md +1 -1
- package/dist/{chunk-BLWJTLRD.js → chunk-DGZ6TM5J.js} +180 -63
- package/dist/cli.cjs +174 -57
- package/dist/cli.js +1 -1
- package/dist/index.cjs +174 -57
- package/dist/index.d.cts +31 -5
- package/dist/index.d.ts +31 -5
- package/dist/index.js +1 -1
- package/package.json +41 -30
package/dist/cli.cjs
CHANGED
|
@@ -354,6 +354,83 @@ var OpenAICompatibleProvider = class extends BaseLLMProvider {
|
|
|
354
354
|
|
|
355
355
|
// src/llm/tasks/categorize.ts
|
|
356
356
|
var import_core3 = require("@releasekit/core");
|
|
357
|
+
|
|
358
|
+
// src/llm/prompts.ts
|
|
359
|
+
function resolvePrompt(taskName, defaultPrompt, promptsConfig) {
|
|
360
|
+
if (!promptsConfig) return defaultPrompt;
|
|
361
|
+
const fullTemplate = promptsConfig.templates?.[taskName];
|
|
362
|
+
if (fullTemplate) return fullTemplate;
|
|
363
|
+
const additionalInstructions = promptsConfig.instructions?.[taskName];
|
|
364
|
+
if (additionalInstructions) {
|
|
365
|
+
const insertionPoint = defaultPrompt.lastIndexOf("Output only valid JSON");
|
|
366
|
+
if (insertionPoint !== -1) {
|
|
367
|
+
return `${defaultPrompt.slice(0, insertionPoint)}Additional instructions:
|
|
368
|
+
${additionalInstructions}
|
|
369
|
+
|
|
370
|
+
${defaultPrompt.slice(insertionPoint)}`;
|
|
371
|
+
}
|
|
372
|
+
return `${defaultPrompt}
|
|
373
|
+
|
|
374
|
+
Additional instructions:
|
|
375
|
+
${additionalInstructions}`;
|
|
376
|
+
}
|
|
377
|
+
return defaultPrompt;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// src/llm/scopes.ts
|
|
381
|
+
function getAllowedScopesFromCategories(categories) {
|
|
382
|
+
const scopeMap = /* @__PURE__ */ new Map();
|
|
383
|
+
for (const cat of categories) {
|
|
384
|
+
if (cat.scopes && cat.scopes.length > 0) {
|
|
385
|
+
scopeMap.set(cat.name, cat.scopes);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
return scopeMap;
|
|
389
|
+
}
|
|
390
|
+
function resolveAllowedScopes(scopeConfig, categories, packageNames) {
|
|
391
|
+
if (!scopeConfig || scopeConfig.mode === "unrestricted") return null;
|
|
392
|
+
if (scopeConfig.mode === "none") return [];
|
|
393
|
+
if (scopeConfig.mode === "packages") return packageNames ?? [];
|
|
394
|
+
if (scopeConfig.mode === "restricted") {
|
|
395
|
+
const explicit = scopeConfig.rules?.allowed ?? [];
|
|
396
|
+
const all = new Set(explicit);
|
|
397
|
+
if (categories) {
|
|
398
|
+
const fromCategories = getAllowedScopesFromCategories(categories);
|
|
399
|
+
for (const scopes of fromCategories.values()) {
|
|
400
|
+
for (const s of scopes) all.add(s);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
return [...all];
|
|
404
|
+
}
|
|
405
|
+
return null;
|
|
406
|
+
}
|
|
407
|
+
function validateScope(scope, allowedScopes, rules) {
|
|
408
|
+
if (!scope || allowedScopes === null) return scope;
|
|
409
|
+
if (allowedScopes.length === 0) return void 0;
|
|
410
|
+
const caseSensitive = rules?.caseSensitive ?? false;
|
|
411
|
+
const normalise = (s) => caseSensitive ? s : s.toLowerCase();
|
|
412
|
+
const isAllowed = allowedScopes.some((a) => normalise(a) === normalise(scope));
|
|
413
|
+
if (isAllowed) return scope;
|
|
414
|
+
switch (rules?.invalidScopeAction ?? "remove") {
|
|
415
|
+
case "keep":
|
|
416
|
+
return scope;
|
|
417
|
+
case "fallback":
|
|
418
|
+
return rules?.fallbackScope;
|
|
419
|
+
case "remove":
|
|
420
|
+
default:
|
|
421
|
+
return void 0;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
function validateEntryScopes(entries, scopeConfig, categories) {
|
|
425
|
+
const allowedScopes = resolveAllowedScopes(scopeConfig, categories);
|
|
426
|
+
if (allowedScopes === null) return entries;
|
|
427
|
+
return entries.map((entry) => ({
|
|
428
|
+
...entry,
|
|
429
|
+
scope: validateScope(entry.scope, allowedScopes, scopeConfig?.rules)
|
|
430
|
+
}));
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// src/llm/tasks/categorize.ts
|
|
357
434
|
var DEFAULT_CATEGORIZE_PROMPT = `You are categorizing changelog entries for a software release.
|
|
358
435
|
|
|
359
436
|
Given the following entries, group them into meaningful categories (e.g., "Core", "UI", "API", "Performance", "Bug Fixes", "Documentation").
|
|
@@ -365,20 +442,21 @@ Entries:
|
|
|
365
442
|
|
|
366
443
|
Output only valid JSON, nothing else:`;
|
|
367
444
|
function buildCustomCategorizePrompt(categories) {
|
|
368
|
-
const categoryList = categories.map((c) =>
|
|
369
|
-
|
|
445
|
+
const categoryList = categories.map((c) => {
|
|
446
|
+
const scopeInfo = c.scopes?.length ? ` Allowed scopes: ${c.scopes.join(", ")}.` : "";
|
|
447
|
+
return `- "${c.name}": ${c.description}${scopeInfo}`;
|
|
448
|
+
}).join("\n");
|
|
449
|
+
const scopeMap = getAllowedScopesFromCategories(categories);
|
|
370
450
|
let scopeInstructions = "";
|
|
371
|
-
if (
|
|
372
|
-
const
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
if (scopes.length > 0) {
|
|
376
|
-
scopeInstructions = `
|
|
377
|
-
|
|
378
|
-
For the "Developer" category, you MUST assign a scope from this exact list: ${scopes.join(", ")}.
|
|
379
|
-
`;
|
|
380
|
-
}
|
|
451
|
+
if (scopeMap.size > 0) {
|
|
452
|
+
const entries = [];
|
|
453
|
+
for (const [catName, scopes] of scopeMap) {
|
|
454
|
+
entries.push(`For "${catName}", assign a scope from: ${scopes.join(", ")}.`);
|
|
381
455
|
}
|
|
456
|
+
scopeInstructions = `
|
|
457
|
+
|
|
458
|
+
${entries.join("\n")}
|
|
459
|
+
Only use scopes from these predefined lists. If an entry does not fit any scope, set scope to null.`;
|
|
382
460
|
}
|
|
383
461
|
return `You are categorizing changelog entries for a software release.
|
|
384
462
|
|
|
@@ -386,9 +464,10 @@ Given the following entries, group them into the specified categories. Only use
|
|
|
386
464
|
|
|
387
465
|
Categories:
|
|
388
466
|
${categoryList}${scopeInstructions}
|
|
467
|
+
|
|
389
468
|
Output a JSON object with two fields:
|
|
390
469
|
- "categories": an object where keys are category names and values are arrays of entry indices (0-based)
|
|
391
|
-
- "scopes": an object where keys are entry indices (as strings) and values are scope labels
|
|
470
|
+
- "scopes": an object where keys are entry indices (as strings) and values are scope labels. Only include entries that have a valid scope from the predefined list.
|
|
392
471
|
|
|
393
472
|
Entries:
|
|
394
473
|
{{entries}}
|
|
@@ -399,9 +478,11 @@ async function categorizeEntries(provider, entries, context) {
|
|
|
399
478
|
if (entries.length === 0) {
|
|
400
479
|
return [];
|
|
401
480
|
}
|
|
402
|
-
const
|
|
481
|
+
const entriesCopy = entries.map((e) => ({ ...e, scope: void 0 }));
|
|
482
|
+
const entriesText = entriesCopy.map((e, i) => `${i}. [${e.type}]: ${e.description}`).join("\n");
|
|
403
483
|
const hasCustomCategories = context.categories && context.categories.length > 0;
|
|
404
|
-
const
|
|
484
|
+
const defaultPrompt = hasCustomCategories ? buildCustomCategorizePrompt(context.categories) : DEFAULT_CATEGORIZE_PROMPT;
|
|
485
|
+
const promptTemplate = resolvePrompt("categorize", defaultPrompt, context.prompts);
|
|
405
486
|
const prompt = promptTemplate.replace("{{entries}}", entriesText);
|
|
406
487
|
try {
|
|
407
488
|
const response = await provider.complete(prompt);
|
|
@@ -413,13 +494,14 @@ async function categorizeEntries(provider, entries, context) {
|
|
|
413
494
|
const scopeMap = parsed.scopes || {};
|
|
414
495
|
for (const [indexStr, scope] of Object.entries(scopeMap)) {
|
|
415
496
|
const idx = Number.parseInt(indexStr, 10);
|
|
416
|
-
if (
|
|
417
|
-
|
|
497
|
+
if (entriesCopy[idx] && scope && scope.trim()) {
|
|
498
|
+
entriesCopy[idx] = { ...entriesCopy[idx], scope: scope.trim() };
|
|
418
499
|
}
|
|
419
500
|
}
|
|
501
|
+
const validatedEntries = validateEntryScopes(entriesCopy, context.scopes, context.categories);
|
|
420
502
|
for (const [category, rawIndices] of Object.entries(categoryMap)) {
|
|
421
503
|
const indices = Array.isArray(rawIndices) ? rawIndices : [];
|
|
422
|
-
const categoryEntries = indices.map((i) =>
|
|
504
|
+
const categoryEntries = indices.map((i) => validatedEntries[i]).filter((e) => e !== void 0);
|
|
423
505
|
if (categoryEntries.length > 0) {
|
|
424
506
|
result.push({ category, entries: categoryEntries });
|
|
425
507
|
}
|
|
@@ -428,7 +510,7 @@ async function categorizeEntries(provider, entries, context) {
|
|
|
428
510
|
const categoryMap = parsed;
|
|
429
511
|
for (const [category, rawIndices] of Object.entries(categoryMap)) {
|
|
430
512
|
const indices = Array.isArray(rawIndices) ? rawIndices : [];
|
|
431
|
-
const categoryEntries = indices.map((i) =>
|
|
513
|
+
const categoryEntries = indices.map((i) => entriesCopy[i]).filter((e) => e !== void 0);
|
|
432
514
|
if (categoryEntries.length > 0) {
|
|
433
515
|
result.push({ category, entries: categoryEntries });
|
|
434
516
|
}
|
|
@@ -439,12 +521,12 @@ async function categorizeEntries(provider, entries, context) {
|
|
|
439
521
|
(0, import_core3.warn)(
|
|
440
522
|
`LLM categorization failed, falling back to General: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
441
523
|
);
|
|
442
|
-
return [{ category: "General", entries }];
|
|
524
|
+
return [{ category: "General", entries: entriesCopy }];
|
|
443
525
|
}
|
|
444
526
|
}
|
|
445
527
|
|
|
446
528
|
// src/llm/tasks/enhance.ts
|
|
447
|
-
var
|
|
529
|
+
var DEFAULT_ENHANCE_PROMPT = `You are improving changelog entries for a software project.
|
|
448
530
|
Given a technical commit message, rewrite it as a clear, user-friendly changelog entry.
|
|
449
531
|
|
|
450
532
|
Rules:
|
|
@@ -460,9 +542,10 @@ Type: {{type}}
|
|
|
460
542
|
Description: {{description}}
|
|
461
543
|
|
|
462
544
|
Rewritten description (only output the new description, nothing else):`;
|
|
463
|
-
async function enhanceEntry(provider, entry,
|
|
464
|
-
const styleText =
|
|
465
|
-
const
|
|
545
|
+
async function enhanceEntry(provider, entry, context) {
|
|
546
|
+
const styleText = context.style ? `- ${context.style}` : '- Use present tense ("Add feature" not "Added feature")';
|
|
547
|
+
const defaultPrompt = DEFAULT_ENHANCE_PROMPT.replace("{{style}}", styleText).replace("{{type}}", entry.type).replace("{{#if scope}}Scope: {{scope}}{{/if}}", entry.scope ? `Scope: ${entry.scope}` : "").replace("{{description}}", entry.description);
|
|
548
|
+
const prompt = resolvePrompt("enhance", defaultPrompt, context.prompts);
|
|
466
549
|
const response = await provider.complete(prompt);
|
|
467
550
|
return response.trim();
|
|
468
551
|
}
|
|
@@ -518,7 +601,23 @@ function buildPrompt(entries, categories, style) {
|
|
|
518
601
|
const entriesText = entries.map((e, i) => `${i}. [${e.type}]${e.scope ? ` (${e.scope})` : ""}: ${e.description}`).join("\n");
|
|
519
602
|
const styleText = style || 'Use present tense ("Add feature" not "Added feature"). Be concise.';
|
|
520
603
|
const categorySection = categories ? `Categories (use ONLY these):
|
|
521
|
-
${categories.map((c) =>
|
|
604
|
+
${categories.map((c) => {
|
|
605
|
+
const scopeInfo = c.scopes?.length ? ` Allowed scopes: ${c.scopes.join(", ")}.` : "";
|
|
606
|
+
return `- "${c.name}": ${c.description}${scopeInfo}`;
|
|
607
|
+
}).join("\n")}` : `Categories: Group into meaningful categories (e.g., "New", "Fixed", "Changed", "Removed").`;
|
|
608
|
+
let scopeInstruction = "";
|
|
609
|
+
if (categories) {
|
|
610
|
+
const scopeMap = getAllowedScopesFromCategories(categories);
|
|
611
|
+
if (scopeMap.size > 0) {
|
|
612
|
+
const parts = [];
|
|
613
|
+
for (const [catName, scopes] of scopeMap) {
|
|
614
|
+
parts.push(`For "${catName}" entries, assign a scope from: ${scopes.join(", ")}.`);
|
|
615
|
+
}
|
|
616
|
+
scopeInstruction = `
|
|
617
|
+
${parts.join("\n")}
|
|
618
|
+
Only use scopes from these predefined lists. Set scope to null if no scope applies.`;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
522
621
|
return `You are generating release notes for a software project. Given the following changelog entries, do two things:
|
|
523
622
|
|
|
524
623
|
1. **Rewrite** each entry as a clear, user-friendly description
|
|
@@ -529,9 +628,7 @@ Style guidelines:
|
|
|
529
628
|
- Be concise (1 short sentence per entry)
|
|
530
629
|
- Focus on what changed, not implementation details
|
|
531
630
|
|
|
532
|
-
${categorySection}
|
|
533
|
-
|
|
534
|
-
${categories ? 'For entries in categories involving internal/developer changes, set a "scope" field with a short subcategory label (e.g., "CI", "Dependencies", "Testing").' : ""}
|
|
631
|
+
${categorySection}${scopeInstruction}
|
|
535
632
|
|
|
536
633
|
Entries:
|
|
537
634
|
${entriesText}
|
|
@@ -548,7 +645,8 @@ async function enhanceAndCategorize(provider, entries, context) {
|
|
|
548
645
|
const retryOpts = LLM_DEFAULTS.retry;
|
|
549
646
|
try {
|
|
550
647
|
return await withRetry(async () => {
|
|
551
|
-
const
|
|
648
|
+
const defaultPrompt = buildPrompt(entries, context.categories, context.style);
|
|
649
|
+
const prompt = resolvePrompt("enhanceAndCategorize", defaultPrompt, context.prompts);
|
|
552
650
|
const response = await provider.complete(prompt);
|
|
553
651
|
const cleaned = response.replace(/^```(?:json)?\n?/, "").replace(/\n?```$/, "").trim();
|
|
554
652
|
const parsed = JSON.parse(cleaned);
|
|
@@ -564,22 +662,23 @@ async function enhanceAndCategorize(provider, entries, context) {
|
|
|
564
662
|
scope: result.scope || original.scope
|
|
565
663
|
};
|
|
566
664
|
});
|
|
665
|
+
const validatedEntries = validateEntryScopes(enhancedEntries, context.scopes, context.categories);
|
|
567
666
|
const categoryMap = /* @__PURE__ */ new Map();
|
|
568
667
|
for (let i = 0; i < parsed.entries.length; i++) {
|
|
569
668
|
const result = parsed.entries[i];
|
|
570
669
|
const category = result?.category || "General";
|
|
571
|
-
const entry =
|
|
670
|
+
const entry = validatedEntries[i];
|
|
572
671
|
if (!entry) continue;
|
|
573
672
|
if (!categoryMap.has(category)) {
|
|
574
673
|
categoryMap.set(category, []);
|
|
575
674
|
}
|
|
576
|
-
categoryMap.get(category)
|
|
675
|
+
categoryMap.get(category)?.push(entry);
|
|
577
676
|
}
|
|
578
677
|
const categories = [];
|
|
579
678
|
for (const [category, catEntries] of categoryMap) {
|
|
580
679
|
categories.push({ category, entries: catEntries });
|
|
581
680
|
}
|
|
582
|
-
return { enhancedEntries, categories };
|
|
681
|
+
return { enhancedEntries: validatedEntries, categories };
|
|
583
682
|
}, retryOpts);
|
|
584
683
|
} catch (error2) {
|
|
585
684
|
(0, import_core4.warn)(
|
|
@@ -593,7 +692,7 @@ async function enhanceAndCategorize(provider, entries, context) {
|
|
|
593
692
|
}
|
|
594
693
|
|
|
595
694
|
// src/llm/tasks/release-notes.ts
|
|
596
|
-
var
|
|
695
|
+
var DEFAULT_RELEASE_NOTES_PROMPT = `You are writing release notes for a software project.
|
|
597
696
|
|
|
598
697
|
Create engaging, user-friendly release notes for the following changes.
|
|
599
698
|
|
|
@@ -626,16 +725,17 @@ No notable changes in this release.`;
|
|
|
626
725
|
if (e.breaking) line += " **BREAKING**";
|
|
627
726
|
return line;
|
|
628
727
|
}).join("\n");
|
|
629
|
-
const
|
|
728
|
+
const defaultPrompt = DEFAULT_RELEASE_NOTES_PROMPT.replace("{{version}}", context.version ?? "v1.0.0").replace(
|
|
630
729
|
"{{#if previousVersion}}Previous version: {{previousVersion}}{{/if}}",
|
|
631
730
|
context.previousVersion ? `Previous version: ${context.previousVersion}` : ""
|
|
632
731
|
).replace("{{date}}", context.date ?? (/* @__PURE__ */ new Date()).toISOString().split("T")[0] ?? "").replace("{{entries}}", entriesText);
|
|
732
|
+
const prompt = resolvePrompt("releaseNotes", defaultPrompt, context.prompts);
|
|
633
733
|
const response = await provider.complete(prompt);
|
|
634
734
|
return response.trim();
|
|
635
735
|
}
|
|
636
736
|
|
|
637
737
|
// src/llm/tasks/summarize.ts
|
|
638
|
-
var
|
|
738
|
+
var DEFAULT_SUMMARIZE_PROMPT = `You are creating a summary of changes for a software release.
|
|
639
739
|
|
|
640
740
|
Given the following changelog entries, create a brief summary (2-3 sentences) that captures the main themes of this release.
|
|
641
741
|
|
|
@@ -643,12 +743,13 @@ Entries:
|
|
|
643
743
|
{{entries}}
|
|
644
744
|
|
|
645
745
|
Summary (only output the summary, nothing else):`;
|
|
646
|
-
async function summarizeEntries(provider, entries,
|
|
746
|
+
async function summarizeEntries(provider, entries, context) {
|
|
647
747
|
if (entries.length === 0) {
|
|
648
748
|
return "";
|
|
649
749
|
}
|
|
650
750
|
const entriesText = entries.map((e) => `- [${e.type}]${e.scope ? ` (${e.scope})` : ""}: ${e.description}`).join("\n");
|
|
651
|
-
const
|
|
751
|
+
const defaultPrompt = DEFAULT_SUMMARIZE_PROMPT.replace("{{entries}}", entriesText);
|
|
752
|
+
const prompt = resolvePrompt("summarize", defaultPrompt, context.prompts);
|
|
652
753
|
const response = await provider.complete(prompt);
|
|
653
754
|
return response.trim();
|
|
654
755
|
}
|
|
@@ -796,9 +897,10 @@ ${body}`;
|
|
|
796
897
|
function writeMarkdown(outputPath, contexts, config, dryRun) {
|
|
797
898
|
const content = renderMarkdown(contexts);
|
|
798
899
|
if (dryRun) {
|
|
799
|
-
(0, import_core5.info)(
|
|
800
|
-
|
|
801
|
-
(0, import_core5.
|
|
900
|
+
(0, import_core5.info)(`Would write changelog to ${outputPath}`);
|
|
901
|
+
(0, import_core5.debug)("--- Changelog Preview ---");
|
|
902
|
+
(0, import_core5.debug)(content);
|
|
903
|
+
(0, import_core5.debug)("--- End Preview ---");
|
|
802
904
|
return;
|
|
803
905
|
}
|
|
804
906
|
const dir = path.dirname(outputPath);
|
|
@@ -957,9 +1059,10 @@ function renderJson(contexts) {
|
|
|
957
1059
|
function writeJson(outputPath, contexts, dryRun) {
|
|
958
1060
|
const content = renderJson(contexts);
|
|
959
1061
|
if (dryRun) {
|
|
960
|
-
(0, import_core7.info)(
|
|
961
|
-
|
|
962
|
-
(0, import_core7.
|
|
1062
|
+
(0, import_core7.info)(`Would write JSON output to ${outputPath}`);
|
|
1063
|
+
(0, import_core7.debug)("--- JSON Output Preview ---");
|
|
1064
|
+
(0, import_core7.debug)(content);
|
|
1065
|
+
(0, import_core7.debug)("--- End Preview ---");
|
|
963
1066
|
return;
|
|
964
1067
|
}
|
|
965
1068
|
const dir = path2.dirname(outputPath);
|
|
@@ -1226,17 +1329,27 @@ function renderTemplate(templatePath, context, engine) {
|
|
|
1226
1329
|
|
|
1227
1330
|
// src/core/pipeline.ts
|
|
1228
1331
|
var import_meta = {};
|
|
1229
|
-
function generateCompareUrl(repoUrl, from, to) {
|
|
1332
|
+
function generateCompareUrl(repoUrl, from, to, packageName) {
|
|
1333
|
+
const isPackageSpecific = from.includes("@") && packageName && from.includes(packageName);
|
|
1334
|
+
let fromVersion;
|
|
1335
|
+
let toVersion;
|
|
1336
|
+
if (isPackageSpecific) {
|
|
1337
|
+
fromVersion = from;
|
|
1338
|
+
toVersion = `${packageName}@${to.startsWith("v") ? "" : "v"}${to}`;
|
|
1339
|
+
} else {
|
|
1340
|
+
fromVersion = from.replace(/^v/, "");
|
|
1341
|
+
toVersion = to.replace(/^v/, "");
|
|
1342
|
+
}
|
|
1230
1343
|
if (/gitlab\.com/i.test(repoUrl)) {
|
|
1231
|
-
return `${repoUrl}/-/compare/${
|
|
1344
|
+
return `${repoUrl}/-/compare/${fromVersion}...${toVersion}`;
|
|
1232
1345
|
}
|
|
1233
1346
|
if (/bitbucket\.org/i.test(repoUrl)) {
|
|
1234
|
-
return `${repoUrl}/branches/compare/${
|
|
1347
|
+
return `${repoUrl}/branches/compare/${fromVersion}..${toVersion}`;
|
|
1235
1348
|
}
|
|
1236
|
-
return `${repoUrl}/compare/${
|
|
1349
|
+
return `${repoUrl}/compare/${fromVersion}...${toVersion}`;
|
|
1237
1350
|
}
|
|
1238
1351
|
function createTemplateContext(pkg) {
|
|
1239
|
-
const compareUrl = pkg.repoUrl && pkg.previousVersion ? generateCompareUrl(pkg.repoUrl, pkg.previousVersion, pkg.version) : void 0;
|
|
1352
|
+
const compareUrl = pkg.repoUrl && pkg.previousVersion ? generateCompareUrl(pkg.repoUrl, pkg.previousVersion, pkg.version, pkg.packageName) : void 0;
|
|
1240
1353
|
return {
|
|
1241
1354
|
packageName: pkg.packageName,
|
|
1242
1355
|
version: pkg.version,
|
|
@@ -1274,7 +1387,9 @@ async function processWithLLM(context, config) {
|
|
|
1274
1387
|
previousVersion: context.previousVersion ?? void 0,
|
|
1275
1388
|
date: context.date,
|
|
1276
1389
|
categories: config.llm.categories,
|
|
1277
|
-
style: config.llm.style
|
|
1390
|
+
style: config.llm.style,
|
|
1391
|
+
scopes: config.llm.scopes,
|
|
1392
|
+
prompts: config.llm.prompts
|
|
1278
1393
|
};
|
|
1279
1394
|
const enhanced = {
|
|
1280
1395
|
entries: context.entries
|
|
@@ -1338,7 +1453,6 @@ async function processWithLLM(context, config) {
|
|
|
1338
1453
|
}
|
|
1339
1454
|
return {
|
|
1340
1455
|
...context,
|
|
1341
|
-
entries: enhanced.entries,
|
|
1342
1456
|
enhanced
|
|
1343
1457
|
};
|
|
1344
1458
|
} catch (error2) {
|
|
@@ -1371,9 +1485,10 @@ async function generateWithTemplate(contexts, config, outputPath, dryRun) {
|
|
|
1371
1485
|
);
|
|
1372
1486
|
const result = renderTemplate(templatePath, documentContext, config.templates?.engine);
|
|
1373
1487
|
if (dryRun) {
|
|
1374
|
-
(0, import_core8.info)(
|
|
1375
|
-
|
|
1376
|
-
(0, import_core8.
|
|
1488
|
+
(0, import_core8.info)(`Would write templated output to ${outputPath}`);
|
|
1489
|
+
(0, import_core8.debug)("--- Changelog Preview ---");
|
|
1490
|
+
(0, import_core8.debug)(result.content);
|
|
1491
|
+
(0, import_core8.debug)("--- End Preview ---");
|
|
1377
1492
|
return;
|
|
1378
1493
|
}
|
|
1379
1494
|
if (outputPath === "-") {
|
|
@@ -1399,8 +1514,10 @@ async function runPipeline(input, config, dryRun) {
|
|
|
1399
1514
|
switch (output.format) {
|
|
1400
1515
|
case "markdown": {
|
|
1401
1516
|
const file = output.file ?? "CHANGELOG.md";
|
|
1402
|
-
|
|
1403
|
-
|
|
1517
|
+
const effectiveTemplateConfig = output.templates ?? config.templates;
|
|
1518
|
+
if (effectiveTemplateConfig?.path || output.options?.template) {
|
|
1519
|
+
const configWithTemplate = { ...config, templates: effectiveTemplateConfig };
|
|
1520
|
+
await generateWithTemplate(contexts, configWithTemplate, file, dryRun);
|
|
1404
1521
|
} else {
|
|
1405
1522
|
writeMarkdown(file, contexts, config, dryRun);
|
|
1406
1523
|
}
|
|
@@ -1460,8 +1577,8 @@ function splitByPackage(contexts) {
|
|
|
1460
1577
|
// src/monorepo/aggregator.ts
|
|
1461
1578
|
function writeFile(outputPath, content, dryRun) {
|
|
1462
1579
|
if (dryRun) {
|
|
1463
|
-
(0, import_core9.info)(`
|
|
1464
|
-
|
|
1580
|
+
(0, import_core9.info)(`Would write to ${outputPath}`);
|
|
1581
|
+
(0, import_core9.debug)(content);
|
|
1465
1582
|
return;
|
|
1466
1583
|
}
|
|
1467
1584
|
const dir = path7.dirname(outputPath);
|