@releasekit/notes 0.3.0-next.4 → 0.3.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.
@@ -1,18 +1,424 @@
1
1
  import {
2
+ EXIT_CODES,
3
+ ReleaseKitError,
4
+ debug,
2
5
  formatVersion,
6
+ info,
3
7
  renderMarkdown,
8
+ success,
9
+ warn,
4
10
  writeMarkdown
5
- } from "./chunk-QCF6V2IY.js";
11
+ } from "./chunk-E4454SIS.js";
12
+
13
+ // ../config/dist/index.js
14
+ import * as fs from "fs";
15
+ import * as path from "path";
16
+ import * as TOML from "smol-toml";
17
+ import * as fs3 from "fs";
18
+ import * as path3 from "path";
19
+ import { z as z2 } from "zod";
20
+ import { z } from "zod";
21
+ import * as fs2 from "fs";
22
+ import * as os from "os";
23
+ import * as path2 from "path";
24
+ var ConfigError = class extends ReleaseKitError {
25
+ code = "CONFIG_ERROR";
26
+ suggestions;
27
+ constructor(message, suggestions) {
28
+ super(message);
29
+ this.suggestions = suggestions ?? [
30
+ "Check that releasekit.config.json exists and is valid JSON",
31
+ "Run with --verbose for more details"
32
+ ];
33
+ }
34
+ };
35
+ var MAX_JSONC_LENGTH = 1e5;
36
+ function parseJsonc(content) {
37
+ if (content.length > MAX_JSONC_LENGTH) {
38
+ throw new Error(`JSONC content too long: ${content.length} characters (max ${MAX_JSONC_LENGTH})`);
39
+ }
40
+ try {
41
+ return JSON.parse(content);
42
+ } catch {
43
+ const cleaned = content.replace(/\/\/[^\r\n]{0,10000}$/gm, "").replace(/\/\*[\s\S]{0,50000}?\*\//g, "").trim();
44
+ return JSON.parse(cleaned);
45
+ }
46
+ }
47
+ var GitConfigSchema = z.object({
48
+ remote: z.string().default("origin"),
49
+ branch: z.string().default("main"),
50
+ pushMethod: z.enum(["auto", "ssh", "https"]).default("auto"),
51
+ /**
52
+ * Optional env var name containing a GitHub token for HTTPS pushes.
53
+ * When set, publish steps can use this token without mutating git remotes.
54
+ */
55
+ httpsTokenEnv: z.string().optional(),
56
+ push: z.boolean().optional(),
57
+ skipHooks: z.boolean().optional()
58
+ });
59
+ var MonorepoConfigSchema = z.object({
60
+ mode: z.enum(["root", "packages", "both"]).optional(),
61
+ rootPath: z.string().optional(),
62
+ packagesPath: z.string().optional(),
63
+ mainPackage: z.string().optional()
64
+ });
65
+ var BranchPatternSchema = z.object({
66
+ pattern: z.string(),
67
+ releaseType: z.enum(["major", "minor", "patch", "prerelease"])
68
+ });
69
+ var VersionCargoConfigSchema = z.object({
70
+ enabled: z.boolean().default(true),
71
+ paths: z.array(z.string()).optional()
72
+ });
73
+ var VersionConfigSchema = z.object({
74
+ tagTemplate: z.string().default("v{version}"),
75
+ packageSpecificTags: z.boolean().default(false),
76
+ preset: z.string().default("conventional"),
77
+ sync: z.boolean().default(true),
78
+ packages: z.array(z.string()).default([]),
79
+ mainPackage: z.string().optional(),
80
+ updateInternalDependencies: z.enum(["major", "minor", "patch", "no-internal-update"]).default("minor"),
81
+ skip: z.array(z.string()).optional(),
82
+ commitMessage: z.string().optional(),
83
+ versionStrategy: z.enum(["branchPattern", "commitMessage"]).default("commitMessage"),
84
+ branchPatterns: z.array(BranchPatternSchema).optional(),
85
+ defaultReleaseType: z.enum(["major", "minor", "patch", "prerelease"]).optional(),
86
+ mismatchStrategy: z.enum(["error", "warn", "ignore", "prefer-package", "prefer-git"]).default("warn"),
87
+ versionPrefix: z.string().default(""),
88
+ prereleaseIdentifier: z.string().optional(),
89
+ strictReachable: z.boolean().default(false),
90
+ cargo: VersionCargoConfigSchema.optional()
91
+ });
92
+ var NpmConfigSchema = z.object({
93
+ enabled: z.boolean().default(true),
94
+ auth: z.enum(["auto", "oidc", "token"]).default("auto"),
95
+ provenance: z.boolean().default(true),
96
+ access: z.enum(["public", "restricted"]).default("public"),
97
+ registry: z.string().default("https://registry.npmjs.org"),
98
+ copyFiles: z.array(z.string()).default(["LICENSE"]),
99
+ tag: z.string().default("latest")
100
+ });
101
+ var CargoPublishConfigSchema = z.object({
102
+ enabled: z.boolean().default(false),
103
+ noVerify: z.boolean().default(false),
104
+ publishOrder: z.array(z.string()).default([]),
105
+ clean: z.boolean().default(false)
106
+ });
107
+ var PublishGitConfigSchema = z.object({
108
+ push: z.boolean().default(true),
109
+ pushMethod: z.enum(["auto", "ssh", "https"]).optional(),
110
+ remote: z.string().optional(),
111
+ branch: z.string().optional(),
112
+ httpsTokenEnv: z.string().optional(),
113
+ skipHooks: z.boolean().optional()
114
+ });
115
+ var GitHubReleaseConfigSchema = z.object({
116
+ enabled: z.boolean().default(true),
117
+ draft: z.boolean().default(true),
118
+ perPackage: z.boolean().default(true),
119
+ prerelease: z.union([z.literal("auto"), z.boolean()]).default("auto"),
120
+ /**
121
+ * Controls how release notes are sourced for GitHub releases.
122
+ * - 'auto': Use RELEASE_NOTES.md if it exists, then per-package changelog
123
+ * data from the version output, then GitHub's auto-generated notes.
124
+ * - 'github': Always use GitHub's auto-generated notes.
125
+ * - 'none': No notes body.
126
+ * - Any other string: Treated as a file path to read notes from.
127
+ */
128
+ releaseNotes: z.union([z.literal("auto"), z.literal("github"), z.literal("none"), z.string()]).default("auto")
129
+ });
130
+ var VerifyRegistryConfigSchema = z.object({
131
+ enabled: z.boolean().default(true),
132
+ maxAttempts: z.number().int().positive().default(5),
133
+ initialDelay: z.number().int().positive().default(15e3),
134
+ backoffMultiplier: z.number().positive().default(2)
135
+ });
136
+ var VerifyConfigSchema = z.object({
137
+ npm: VerifyRegistryConfigSchema.default({
138
+ enabled: true,
139
+ maxAttempts: 5,
140
+ initialDelay: 15e3,
141
+ backoffMultiplier: 2
142
+ }),
143
+ cargo: VerifyRegistryConfigSchema.default({
144
+ enabled: true,
145
+ maxAttempts: 10,
146
+ initialDelay: 3e4,
147
+ backoffMultiplier: 2
148
+ })
149
+ });
150
+ var PublishConfigSchema = z.object({
151
+ git: PublishGitConfigSchema.optional(),
152
+ npm: NpmConfigSchema.default({
153
+ enabled: true,
154
+ auth: "auto",
155
+ provenance: true,
156
+ access: "public",
157
+ registry: "https://registry.npmjs.org",
158
+ copyFiles: ["LICENSE"],
159
+ tag: "latest"
160
+ }),
161
+ cargo: CargoPublishConfigSchema.default({
162
+ enabled: false,
163
+ noVerify: false,
164
+ publishOrder: [],
165
+ clean: false
166
+ }),
167
+ githubRelease: GitHubReleaseConfigSchema.default({
168
+ enabled: true,
169
+ draft: true,
170
+ perPackage: true,
171
+ prerelease: "auto",
172
+ releaseNotes: "auto"
173
+ }),
174
+ verify: VerifyConfigSchema.default({
175
+ npm: {
176
+ enabled: true,
177
+ maxAttempts: 5,
178
+ initialDelay: 15e3,
179
+ backoffMultiplier: 2
180
+ },
181
+ cargo: {
182
+ enabled: true,
183
+ maxAttempts: 10,
184
+ initialDelay: 3e4,
185
+ backoffMultiplier: 2
186
+ }
187
+ })
188
+ });
189
+ var TemplateConfigSchema = z.object({
190
+ path: z.string().optional(),
191
+ engine: z.enum(["handlebars", "liquid", "ejs"]).optional()
192
+ });
193
+ var OutputConfigSchema = z.object({
194
+ format: z.enum(["markdown", "github-release", "json"]),
195
+ file: z.string().optional(),
196
+ options: z.record(z.string(), z.unknown()).optional(),
197
+ templates: TemplateConfigSchema.optional()
198
+ });
199
+ var LLMOptionsSchema = z.object({
200
+ timeout: z.number().optional(),
201
+ maxTokens: z.number().optional(),
202
+ temperature: z.number().optional()
203
+ });
204
+ var LLMRetryConfigSchema = z.object({
205
+ maxAttempts: z.number().int().positive().optional(),
206
+ initialDelay: z.number().nonnegative().optional(),
207
+ maxDelay: z.number().positive().optional(),
208
+ backoffFactor: z.number().positive().optional()
209
+ });
210
+ var LLMTasksConfigSchema = z.object({
211
+ summarize: z.boolean().optional(),
212
+ enhance: z.boolean().optional(),
213
+ categorize: z.boolean().optional(),
214
+ releaseNotes: z.boolean().optional()
215
+ });
216
+ var LLMCategorySchema = z.object({
217
+ name: z.string(),
218
+ description: z.string(),
219
+ scopes: z.array(z.string()).optional()
220
+ });
221
+ var ScopeRulesSchema = z.object({
222
+ allowed: z.array(z.string()).optional(),
223
+ caseSensitive: z.boolean().default(false),
224
+ invalidScopeAction: z.enum(["remove", "keep", "fallback"]).default("remove"),
225
+ fallbackScope: z.string().optional()
226
+ });
227
+ var ScopeConfigSchema = z.object({
228
+ mode: z.enum(["restricted", "packages", "none", "unrestricted"]).default("unrestricted"),
229
+ rules: ScopeRulesSchema.optional()
230
+ });
231
+ var LLMPromptOverridesSchema = z.object({
232
+ enhance: z.string().optional(),
233
+ categorize: z.string().optional(),
234
+ enhanceAndCategorize: z.string().optional(),
235
+ summarize: z.string().optional(),
236
+ releaseNotes: z.string().optional()
237
+ });
238
+ var LLMPromptsConfigSchema = z.object({
239
+ instructions: LLMPromptOverridesSchema.optional(),
240
+ templates: LLMPromptOverridesSchema.optional()
241
+ });
242
+ var LLMConfigSchema = z.object({
243
+ provider: z.string(),
244
+ model: z.string(),
245
+ baseURL: z.string().optional(),
246
+ apiKey: z.string().optional(),
247
+ options: LLMOptionsSchema.optional(),
248
+ concurrency: z.number().int().positive().optional(),
249
+ retry: LLMRetryConfigSchema.optional(),
250
+ tasks: LLMTasksConfigSchema.optional(),
251
+ categories: z.array(LLMCategorySchema).optional(),
252
+ style: z.string().optional(),
253
+ scopes: ScopeConfigSchema.optional(),
254
+ prompts: LLMPromptsConfigSchema.optional()
255
+ });
256
+ var NotesInputConfigSchema = z.object({
257
+ source: z.string().optional(),
258
+ file: z.string().optional()
259
+ });
260
+ var NotesConfigSchema = z.object({
261
+ input: NotesInputConfigSchema.optional(),
262
+ output: z.array(OutputConfigSchema).default([{ format: "markdown", file: "CHANGELOG.md" }]),
263
+ monorepo: MonorepoConfigSchema.optional(),
264
+ templates: TemplateConfigSchema.optional(),
265
+ llm: LLMConfigSchema.optional(),
266
+ updateStrategy: z.enum(["prepend", "regenerate"]).default("prepend")
267
+ });
268
+ var CILabelsConfigSchema = z.object({
269
+ stable: z.string().default("release:stable"),
270
+ prerelease: z.string().default("release:prerelease"),
271
+ skip: z.string().default("release:skip"),
272
+ major: z.string().default("release:major"),
273
+ minor: z.string().default("release:minor"),
274
+ patch: z.string().default("release:patch")
275
+ });
276
+ var CIConfigSchema = z.object({
277
+ releaseStrategy: z.enum(["manual", "direct", "standing-pr", "scheduled"]).default("direct"),
278
+ releaseTrigger: z.enum(["commit", "label"]).default("label"),
279
+ prPreview: z.boolean().default(true),
280
+ autoRelease: z.boolean().default(false),
281
+ /**
282
+ * Commit message prefixes that should not trigger a release.
283
+ * Defaults to `['chore: release ']` to match the release commit template
284
+ * (`chore: release ${packageName} v${version}`) and provide a
285
+ * secondary loop-prevention guard alongside `[skip ci]`.
286
+ */
287
+ skipPatterns: z.array(z.string()).default(["chore: release "]),
288
+ minChanges: z.number().int().positive().default(1),
289
+ labels: CILabelsConfigSchema.default({
290
+ stable: "release:stable",
291
+ prerelease: "release:prerelease",
292
+ skip: "release:skip",
293
+ major: "release:major",
294
+ minor: "release:minor",
295
+ patch: "release:patch"
296
+ })
297
+ });
298
+ var ReleaseCIConfigSchema = z.object({
299
+ skipPatterns: z.array(z.string().min(1)).optional(),
300
+ minChanges: z.number().int().positive().optional(),
301
+ /** Set to `false` to disable GitHub release creation in CI. */
302
+ githubRelease: z.literal(false).optional(),
303
+ /** Set to `false` to disable changelog generation in CI. */
304
+ notes: z.literal(false).optional()
305
+ });
306
+ var ReleaseConfigSchema = z.object({
307
+ /**
308
+ * Optional steps to enable. The version step always runs; only 'notes' and
309
+ * 'publish' can be opted out. Omitting a step is equivalent to --skip-<step>.
310
+ */
311
+ steps: z.array(z.enum(["notes", "publish"])).min(1).optional(),
312
+ ci: ReleaseCIConfigSchema.optional()
313
+ });
314
+ var ReleaseKitConfigSchema = z.object({
315
+ git: GitConfigSchema.optional(),
316
+ monorepo: MonorepoConfigSchema.optional(),
317
+ version: VersionConfigSchema.optional(),
318
+ publish: PublishConfigSchema.optional(),
319
+ notes: NotesConfigSchema.optional(),
320
+ ci: CIConfigSchema.optional(),
321
+ release: ReleaseConfigSchema.optional()
322
+ });
323
+ var MAX_INPUT_LENGTH = 1e4;
324
+ function substituteVariables(value) {
325
+ if (value.length > MAX_INPUT_LENGTH) {
326
+ throw new Error(`Input too long: ${value.length} characters (max ${MAX_INPUT_LENGTH})`);
327
+ }
328
+ const envPattern = /\{env:([^}]{1,1000})\}/g;
329
+ const filePattern = /\{file:([^}]{1,1000})\}/g;
330
+ let result = value;
331
+ result = result.replace(envPattern, (_, varName) => {
332
+ return process.env[varName] ?? "";
333
+ });
334
+ result = result.replace(filePattern, (_, filePath) => {
335
+ const expandedPath = filePath.startsWith("~") ? path2.join(os.homedir(), filePath.slice(1)) : filePath;
336
+ try {
337
+ return fs2.readFileSync(expandedPath, "utf-8").trim();
338
+ } catch {
339
+ return "";
340
+ }
341
+ });
342
+ return result;
343
+ }
344
+ var SOLE_REFERENCE_PATTERN = /^\{(?:env|file):[^}]+\}$/;
345
+ function substituteInObject(obj) {
346
+ if (typeof obj === "string") {
347
+ const result = substituteVariables(obj);
348
+ if (result === "" && SOLE_REFERENCE_PATTERN.test(obj)) {
349
+ return void 0;
350
+ }
351
+ return result;
352
+ }
353
+ if (Array.isArray(obj)) {
354
+ return obj.map((item) => substituteInObject(item));
355
+ }
356
+ if (obj && typeof obj === "object") {
357
+ const result = {};
358
+ for (const [key, value] of Object.entries(obj)) {
359
+ result[key] = substituteInObject(value);
360
+ }
361
+ return result;
362
+ }
363
+ return obj;
364
+ }
365
+ var AUTH_DIR = path2.join(os.homedir(), ".config", "releasekit");
366
+ var AUTH_FILE = path2.join(AUTH_DIR, "auth.json");
367
+ function loadAuth() {
368
+ if (fs2.existsSync(AUTH_FILE)) {
369
+ try {
370
+ const content = fs2.readFileSync(AUTH_FILE, "utf-8");
371
+ return JSON.parse(content);
372
+ } catch {
373
+ return {};
374
+ }
375
+ }
376
+ return {};
377
+ }
378
+ function saveAuth(provider, apiKey) {
379
+ if (!fs2.existsSync(AUTH_DIR)) {
380
+ fs2.mkdirSync(AUTH_DIR, { recursive: true });
381
+ }
382
+ const existing = loadAuth();
383
+ existing[provider] = apiKey;
384
+ fs2.writeFileSync(AUTH_FILE, JSON.stringify(existing, null, 2), { encoding: "utf-8", mode: 384 });
385
+ }
386
+ var CONFIG_FILE = "releasekit.config.json";
387
+ function loadConfigFile(configPath) {
388
+ if (!fs3.existsSync(configPath)) {
389
+ return {};
390
+ }
391
+ try {
392
+ const content = fs3.readFileSync(configPath, "utf-8");
393
+ const parsed = parseJsonc(content);
394
+ const substituted = substituteInObject(parsed);
395
+ return ReleaseKitConfigSchema.parse(substituted);
396
+ } catch (error) {
397
+ if (error instanceof z2.ZodError) {
398
+ const issues = error.issues.map((i) => ` ${i.path.join(".")}: ${i.message}`).join("\n");
399
+ throw new ConfigError(`Config validation errors:
400
+ ${issues}`);
401
+ }
402
+ if (error instanceof SyntaxError) {
403
+ throw new ConfigError(`Invalid JSON in config file: ${error.message}`);
404
+ }
405
+ throw error;
406
+ }
407
+ }
408
+ function loadConfig(options) {
409
+ const cwd = options?.cwd ?? process.cwd();
410
+ const configPath = options?.configPath ?? path3.join(cwd, CONFIG_FILE);
411
+ return loadConfigFile(configPath);
412
+ }
413
+ function loadNotesConfig(options) {
414
+ const config = loadConfig(options);
415
+ return config.notes;
416
+ }
6
417
 
7
418
  // src/core/config.ts
8
- import {
9
- loadAuth,
10
- loadNotesConfig as loadSharedNotesConfig,
11
- saveAuth
12
- } from "@releasekit/config";
13
- function loadConfig(projectDir = process.cwd(), configFile) {
419
+ function loadConfig2(projectDir = process.cwd(), configFile) {
14
420
  const options = { cwd: projectDir, configPath: configFile };
15
- return loadSharedNotesConfig(options) ?? getDefaultConfig();
421
+ return loadNotesConfig(options) ?? getDefaultConfig();
16
422
  }
17
423
  function getDefaultConfig() {
18
424
  return {
@@ -22,8 +428,6 @@ function getDefaultConfig() {
22
428
  }
23
429
 
24
430
  // src/errors/index.ts
25
- import { EXIT_CODES, ReleaseKitError } from "@releasekit/core";
26
- import { EXIT_CODES as EXIT_CODES2 } from "@releasekit/core";
27
431
  var NotesError = class extends ReleaseKitError {
28
432
  };
29
433
  var InputParseError = class extends NotesError {
@@ -59,7 +463,7 @@ var GitHubError = class extends NotesError {
59
463
  "Verify repository exists and is accessible"
60
464
  ];
61
465
  };
62
- var ConfigError = class extends NotesError {
466
+ var ConfigError2 = class extends NotesError {
63
467
  code = "CONFIG_ERROR";
64
468
  suggestions = [
65
469
  "Check config file syntax",
@@ -84,8 +488,8 @@ function getExitCode(error) {
84
488
  }
85
489
  }
86
490
 
87
- // src/input/package-versioner.ts
88
- import * as fs from "fs";
491
+ // src/input/version-output.ts
492
+ import * as fs4 from "fs";
89
493
  function normalizeEntryType(type) {
90
494
  const typeMap = {
91
495
  added: "added",
@@ -103,7 +507,7 @@ function normalizeEntryType(type) {
103
507
  };
104
508
  return typeMap[type.toLowerCase()] ?? "changed";
105
509
  }
106
- function parsePackageVersioner(json) {
510
+ function parseVersionOutput(json) {
107
511
  let data;
108
512
  try {
109
513
  data = JSON.parse(json);
@@ -131,30 +535,29 @@ function parsePackageVersioner(json) {
131
535
  }));
132
536
  const repoUrl = packages[0]?.repoUrl ?? null;
133
537
  return {
134
- source: "package-versioner",
538
+ source: "version",
135
539
  packages,
136
540
  metadata: {
137
541
  repoUrl: repoUrl ?? void 0
138
542
  }
139
543
  };
140
544
  }
141
- function parsePackageVersionerFile(filePath) {
142
- const content = fs.readFileSync(filePath, "utf-8");
143
- return parsePackageVersioner(content);
545
+ function parseVersionOutputFile(filePath) {
546
+ const content = fs4.readFileSync(filePath, "utf-8");
547
+ return parseVersionOutput(content);
144
548
  }
145
- async function parsePackageVersionerStdin() {
549
+ async function parseVersionOutputStdin() {
146
550
  const chunks = [];
147
551
  for await (const chunk of process.stdin) {
148
552
  chunks.push(chunk);
149
553
  }
150
554
  const content = chunks.join("");
151
- return parsePackageVersioner(content);
555
+ return parseVersionOutput(content);
152
556
  }
153
557
 
154
558
  // src/output/json.ts
155
- import * as fs2 from "fs";
156
- import * as path from "path";
157
- import { debug, info, success } from "@releasekit/core";
559
+ import * as fs5 from "fs";
560
+ import * as path4 from "path";
158
561
  function renderJson(contexts) {
159
562
  return JSON.stringify(
160
563
  {
@@ -180,23 +583,22 @@ function writeJson(outputPath, contexts, dryRun) {
180
583
  debug("--- End Preview ---");
181
584
  return;
182
585
  }
183
- const dir = path.dirname(outputPath);
184
- if (!fs2.existsSync(dir)) {
185
- fs2.mkdirSync(dir, { recursive: true });
586
+ const dir = path4.dirname(outputPath);
587
+ if (!fs5.existsSync(dir)) {
588
+ fs5.mkdirSync(dir, { recursive: true });
186
589
  }
187
- fs2.writeFileSync(outputPath, content, "utf-8");
590
+ fs5.writeFileSync(outputPath, content, "utf-8");
188
591
  success(`JSON output written to ${outputPath}`);
189
592
  }
190
593
 
191
594
  // src/core/pipeline.ts
192
- import * as fs7 from "fs";
193
- import * as path5 from "path";
194
- import { debug as debug2, info as info3, success as success3, warn as warn3 } from "@releasekit/core";
595
+ import * as fs10 from "fs";
596
+ import * as path8 from "path";
195
597
 
196
598
  // src/llm/defaults.ts
197
599
  var LLM_DEFAULTS = {
198
600
  timeout: 6e4,
199
- maxTokens: 2e3,
601
+ maxTokens: 4e3,
200
602
  temperature: 0.7,
201
603
  concurrency: 5,
202
604
  retry: {
@@ -386,8 +788,15 @@ var OpenAICompatibleProvider = class extends BaseLLMProvider {
386
788
  }
387
789
  };
388
790
 
389
- // src/llm/tasks/categorize.ts
390
- import { warn } from "@releasekit/core";
791
+ // src/utils/json.ts
792
+ function extractJsonFromResponse(response) {
793
+ const stripped = response.replace(/^```(?:json)?\n?/, "").replace(/\n?```$/, "").trim();
794
+ const objectMatch = stripped.match(/\{[\s\S]*\}/);
795
+ if (objectMatch) return objectMatch[0];
796
+ const arrayMatch = stripped.match(/\[[\s\S]*\]/);
797
+ if (arrayMatch) return arrayMatch[0];
798
+ return stripped;
799
+ }
391
800
 
392
801
  // src/llm/prompts.ts
393
802
  function resolvePrompt(taskName, defaultPrompt, promptsConfig) {
@@ -519,8 +928,7 @@ async function categorizeEntries(provider, entries, context) {
519
928
  const prompt = promptTemplate.replace("{{entries}}", entriesText);
520
929
  try {
521
930
  const response = await provider.complete(prompt);
522
- const cleaned = response.replace(/^```(?:json)?\n?/, "").replace(/\n?```$/, "").trim();
523
- const parsed = JSON.parse(cleaned);
931
+ const parsed = JSON.parse(extractJsonFromResponse(response));
524
932
  const result = [];
525
933
  if (hasCustomCategories && parsed.categories) {
526
934
  const categoryMap = parsed.categories;
@@ -601,9 +1009,6 @@ async function enhanceEntries(provider, entries, context, concurrency = LLM_DEFA
601
1009
  return results;
602
1010
  }
603
1011
 
604
- // src/llm/tasks/enhance-and-categorize.ts
605
- import { warn as warn2 } from "@releasekit/core";
606
-
607
1012
  // src/utils/retry.ts
608
1013
  function sleep(ms) {
609
1014
  return new Promise((resolve2) => setTimeout(resolve2, ms));
@@ -681,8 +1086,7 @@ async function enhanceAndCategorize(provider, entries, context) {
681
1086
  const defaultPrompt = buildPrompt(entries, context.categories, context.style);
682
1087
  const prompt = resolvePrompt("enhanceAndCategorize", defaultPrompt, context.prompts);
683
1088
  const response = await provider.complete(prompt);
684
- const cleaned = response.replace(/^```(?:json)?\n?/, "").replace(/\n?```$/, "").trim();
685
- const parsed = JSON.parse(cleaned);
1089
+ const parsed = JSON.parse(extractJsonFromResponse(response));
686
1090
  if (!Array.isArray(parsed.entries)) {
687
1091
  throw new Error('Response missing "entries" array');
688
1092
  }
@@ -714,7 +1118,7 @@ async function enhanceAndCategorize(provider, entries, context) {
714
1118
  return { enhancedEntries: validatedEntries, categories };
715
1119
  }, retryOpts);
716
1120
  } catch (error) {
717
- warn2(
1121
+ warn(
718
1122
  `Combined enhance+categorize failed after ${retryOpts.maxAttempts} attempts: ${error instanceof Error ? error.message : String(error)}`
719
1123
  );
720
1124
  return {
@@ -826,7 +1230,6 @@ function createProvider(config) {
826
1230
 
827
1231
  // src/output/github-release.ts
828
1232
  import { Octokit } from "@octokit/rest";
829
- import { info as info2, success as success2 } from "@releasekit/core";
830
1233
  var GitHubClient = class {
831
1234
  octokit;
832
1235
  owner;
@@ -848,7 +1251,7 @@ var GitHubClient = class {
848
1251
  } else {
849
1252
  body = renderMarkdown([context]);
850
1253
  }
851
- info2(`Creating GitHub release for ${tagName}`);
1254
+ info(`Creating GitHub release for ${tagName}`);
852
1255
  try {
853
1256
  const response = await this.octokit.repos.createRelease({
854
1257
  owner: this.owner,
@@ -860,7 +1263,7 @@ var GitHubClient = class {
860
1263
  prerelease: options.prerelease ?? false,
861
1264
  generate_release_notes: options.generateNotes ?? false
862
1265
  });
863
- success2(`Release created: ${response.data.html_url}`);
1266
+ success(`Release created: ${response.data.html_url}`);
864
1267
  return {
865
1268
  id: response.data.id,
866
1269
  htmlUrl: response.data.html_url,
@@ -878,7 +1281,7 @@ var GitHubClient = class {
878
1281
  } else {
879
1282
  body = renderMarkdown([context]);
880
1283
  }
881
- info2(`Updating GitHub release ${releaseId}`);
1284
+ info(`Updating GitHub release ${releaseId}`);
882
1285
  try {
883
1286
  const response = await this.octokit.repos.updateRelease({
884
1287
  owner: this.owner,
@@ -890,7 +1293,7 @@ var GitHubClient = class {
890
1293
  draft: options.draft ?? false,
891
1294
  prerelease: options.prerelease ?? false
892
1295
  });
893
- success2(`Release updated: ${response.data.html_url}`);
1296
+ success(`Release updated: ${response.data.html_url}`);
894
1297
  return {
895
1298
  id: response.data.id,
896
1299
  htmlUrl: response.data.html_url,
@@ -940,7 +1343,7 @@ async function createGitHubRelease(context, options) {
940
1343
  }
941
1344
 
942
1345
  // src/templates/ejs.ts
943
- import * as fs3 from "fs";
1346
+ import * as fs6 from "fs";
944
1347
  import ejs from "ejs";
945
1348
  function renderEjs(template, context) {
946
1349
  try {
@@ -950,16 +1353,16 @@ function renderEjs(template, context) {
950
1353
  }
951
1354
  }
952
1355
  function renderEjsFile(filePath, context) {
953
- if (!fs3.existsSync(filePath)) {
1356
+ if (!fs6.existsSync(filePath)) {
954
1357
  throw new TemplateError(`Template file not found: ${filePath}`);
955
1358
  }
956
- const template = fs3.readFileSync(filePath, "utf-8");
1359
+ const template = fs6.readFileSync(filePath, "utf-8");
957
1360
  return renderEjs(template, context);
958
1361
  }
959
1362
 
960
1363
  // src/templates/handlebars.ts
961
- import * as fs4 from "fs";
962
- import * as path2 from "path";
1364
+ import * as fs7 from "fs";
1365
+ import * as path5 from "path";
963
1366
  import Handlebars from "handlebars";
964
1367
  function registerHandlebarsHelpers() {
965
1368
  Handlebars.registerHelper("capitalize", (str) => {
@@ -985,28 +1388,28 @@ function renderHandlebars(template, context) {
985
1388
  }
986
1389
  }
987
1390
  function renderHandlebarsFile(filePath, context) {
988
- if (!fs4.existsSync(filePath)) {
1391
+ if (!fs7.existsSync(filePath)) {
989
1392
  throw new TemplateError(`Template file not found: ${filePath}`);
990
1393
  }
991
- const template = fs4.readFileSync(filePath, "utf-8");
1394
+ const template = fs7.readFileSync(filePath, "utf-8");
992
1395
  return renderHandlebars(template, context);
993
1396
  }
994
1397
  function renderHandlebarsComposable(templateDir, context) {
995
1398
  registerHandlebarsHelpers();
996
- const versionPath = path2.join(templateDir, "version.hbs");
997
- const entryPath = path2.join(templateDir, "entry.hbs");
998
- const documentPath = path2.join(templateDir, "document.hbs");
999
- if (!fs4.existsSync(documentPath)) {
1399
+ const versionPath = path5.join(templateDir, "version.hbs");
1400
+ const entryPath = path5.join(templateDir, "entry.hbs");
1401
+ const documentPath = path5.join(templateDir, "document.hbs");
1402
+ if (!fs7.existsSync(documentPath)) {
1000
1403
  throw new TemplateError(`Document template not found: ${documentPath}`);
1001
1404
  }
1002
- if (fs4.existsSync(versionPath)) {
1003
- Handlebars.registerPartial("version", fs4.readFileSync(versionPath, "utf-8"));
1405
+ if (fs7.existsSync(versionPath)) {
1406
+ Handlebars.registerPartial("version", fs7.readFileSync(versionPath, "utf-8"));
1004
1407
  }
1005
- if (fs4.existsSync(entryPath)) {
1006
- Handlebars.registerPartial("entry", fs4.readFileSync(entryPath, "utf-8"));
1408
+ if (fs7.existsSync(entryPath)) {
1409
+ Handlebars.registerPartial("entry", fs7.readFileSync(entryPath, "utf-8"));
1007
1410
  }
1008
1411
  try {
1009
- const compiled = Handlebars.compile(fs4.readFileSync(documentPath, "utf-8"));
1412
+ const compiled = Handlebars.compile(fs7.readFileSync(documentPath, "utf-8"));
1010
1413
  return compiled(context);
1011
1414
  } catch (error) {
1012
1415
  throw new TemplateError(`Handlebars render error: ${error instanceof Error ? error.message : String(error)}`);
@@ -1014,8 +1417,8 @@ function renderHandlebarsComposable(templateDir, context) {
1014
1417
  }
1015
1418
 
1016
1419
  // src/templates/liquid.ts
1017
- import * as fs5 from "fs";
1018
- import * as path3 from "path";
1420
+ import * as fs8 from "fs";
1421
+ import * as path6 from "path";
1019
1422
  import { Liquid } from "liquidjs";
1020
1423
  function createLiquidEngine(root) {
1021
1424
  return new Liquid({
@@ -1033,15 +1436,15 @@ function renderLiquid(template, context) {
1033
1436
  }
1034
1437
  }
1035
1438
  function renderLiquidFile(filePath, context) {
1036
- if (!fs5.existsSync(filePath)) {
1439
+ if (!fs8.existsSync(filePath)) {
1037
1440
  throw new TemplateError(`Template file not found: ${filePath}`);
1038
1441
  }
1039
- const template = fs5.readFileSync(filePath, "utf-8");
1442
+ const template = fs8.readFileSync(filePath, "utf-8");
1040
1443
  return renderLiquid(template, context);
1041
1444
  }
1042
1445
  function renderLiquidComposable(templateDir, context) {
1043
- const documentPath = path3.join(templateDir, "document.liquid");
1044
- if (!fs5.existsSync(documentPath)) {
1446
+ const documentPath = path6.join(templateDir, "document.liquid");
1447
+ if (!fs8.existsSync(documentPath)) {
1045
1448
  throw new TemplateError(`Document template not found: ${documentPath}`);
1046
1449
  }
1047
1450
  const engine = createLiquidEngine(templateDir);
@@ -1053,10 +1456,10 @@ function renderLiquidComposable(templateDir, context) {
1053
1456
  }
1054
1457
 
1055
1458
  // src/templates/loader.ts
1056
- import * as fs6 from "fs";
1057
- import * as path4 from "path";
1459
+ import * as fs9 from "fs";
1460
+ import * as path7 from "path";
1058
1461
  function getEngineFromFile(filePath) {
1059
- const ext = path4.extname(filePath).toLowerCase();
1462
+ const ext = path7.extname(filePath).toLowerCase();
1060
1463
  switch (ext) {
1061
1464
  case ".liquid":
1062
1465
  return "liquid";
@@ -1090,10 +1493,10 @@ function getRenderFileFn(engine) {
1090
1493
  }
1091
1494
  }
1092
1495
  function detectTemplateMode(templatePath) {
1093
- if (!fs6.existsSync(templatePath)) {
1496
+ if (!fs9.existsSync(templatePath)) {
1094
1497
  throw new TemplateError(`Template path not found: ${templatePath}`);
1095
1498
  }
1096
- const stat = fs6.statSync(templatePath);
1499
+ const stat = fs9.statSync(templatePath);
1097
1500
  if (stat.isFile()) {
1098
1501
  return "single";
1099
1502
  }
@@ -1111,7 +1514,7 @@ function renderSingleFile(templatePath, context, engine) {
1111
1514
  };
1112
1515
  }
1113
1516
  function renderComposable(templateDir, context, engine) {
1114
- const files = fs6.readdirSync(templateDir);
1517
+ const files = fs9.readdirSync(templateDir);
1115
1518
  const engineMap = {
1116
1519
  liquid: { document: "document.liquid", version: "version.liquid", entry: "entry.liquid" },
1117
1520
  handlebars: { document: "document.hbs", version: "version.hbs", entry: "entry.hbs" },
@@ -1134,15 +1537,15 @@ function renderComposable(templateDir, context, engine) {
1134
1537
  return { content: renderHandlebarsComposable(templateDir, context), engine: resolvedEngine };
1135
1538
  }
1136
1539
  const expectedFiles = engineMap[resolvedEngine];
1137
- const documentPath = path4.join(templateDir, expectedFiles.document);
1138
- if (!fs6.existsSync(documentPath)) {
1540
+ const documentPath = path7.join(templateDir, expectedFiles.document);
1541
+ if (!fs9.existsSync(documentPath)) {
1139
1542
  throw new TemplateError(`Document template not found: ${expectedFiles.document}`);
1140
1543
  }
1141
- const versionPath = path4.join(templateDir, expectedFiles.version);
1142
- const entryPath = path4.join(templateDir, expectedFiles.entry);
1544
+ const versionPath = path7.join(templateDir, expectedFiles.version);
1545
+ const entryPath = path7.join(templateDir, expectedFiles.entry);
1143
1546
  const render = getRenderFn(resolvedEngine);
1144
- const entryTemplate = fs6.existsSync(entryPath) ? fs6.readFileSync(entryPath, "utf-8") : null;
1145
- const versionTemplate = fs6.existsSync(versionPath) ? fs6.readFileSync(versionPath, "utf-8") : null;
1547
+ const entryTemplate = fs9.existsSync(entryPath) ? fs9.readFileSync(entryPath, "utf-8") : null;
1548
+ const versionTemplate = fs9.existsSync(versionPath) ? fs9.readFileSync(versionPath, "utf-8") : null;
1146
1549
  if (entryTemplate && versionTemplate) {
1147
1550
  const versionsWithEntries = context.versions.map((versionCtx) => {
1148
1551
  const entries = versionCtx.entries.map((entry) => {
@@ -1153,7 +1556,7 @@ function renderComposable(templateDir, context, engine) {
1153
1556
  });
1154
1557
  const docContext = { ...context, renderedVersions: versionsWithEntries };
1155
1558
  return {
1156
- content: render(fs6.readFileSync(documentPath, "utf-8"), docContext),
1559
+ content: render(fs9.readFileSync(documentPath, "utf-8"), docContext),
1157
1560
  engine: resolvedEngine
1158
1561
  };
1159
1562
  }
@@ -1213,6 +1616,16 @@ function generateCompareUrl(repoUrl, from, to, packageName) {
1213
1616
  }
1214
1617
  return `${repoUrl}/compare/${fromVersion}...${toVersion}`;
1215
1618
  }
1619
+ function buildOrderedCategories(rawCategories, configCategories) {
1620
+ const order = configCategories?.map((c) => c.name) ?? [];
1621
+ const mapped = rawCategories.map((c) => ({ name: c.category, entries: c.entries }));
1622
+ if (order.length === 0) return mapped;
1623
+ return mapped.sort((a, b) => {
1624
+ const ai = order.indexOf(a.name);
1625
+ const bi = order.indexOf(b.name);
1626
+ return (ai === -1 ? order.length : ai) - (bi === -1 ? order.length : bi);
1627
+ });
1628
+ }
1216
1629
  function createTemplateContext(pkg) {
1217
1630
  const compareUrl = pkg.repoUrl && pkg.previousVersion ? generateCompareUrl(pkg.repoUrl, pkg.previousVersion, pkg.version, pkg.packageName) : void 0;
1218
1631
  return {
@@ -1260,60 +1673,57 @@ async function processWithLLM(context, config) {
1260
1673
  entries: context.entries
1261
1674
  };
1262
1675
  try {
1263
- info3(`Using LLM provider: ${config.llm.provider}${config.llm.model ? ` (${config.llm.model})` : ""}`);
1676
+ info(`Using LLM provider: ${config.llm.provider}${config.llm.model ? ` (${config.llm.model})` : ""}`);
1264
1677
  if (config.llm.baseURL) {
1265
- info3(`LLM base URL: ${config.llm.baseURL}`);
1678
+ info(`LLM base URL: ${config.llm.baseURL}`);
1266
1679
  }
1267
1680
  const rawProvider = createProvider(config.llm);
1268
1681
  const retryOpts = config.llm.retry ?? LLM_DEFAULTS.retry;
1682
+ const configOptions = config.llm.options;
1269
1683
  const provider = {
1270
1684
  name: rawProvider.name,
1271
- complete: (prompt, opts) => withRetry(() => rawProvider.complete(prompt, opts), retryOpts)
1685
+ // Merge user-configured options (timeout, maxTokens, temperature) as base defaults,
1686
+ // allowing any per-call overrides to take precedence.
1687
+ complete: (prompt, opts) => withRetry(() => rawProvider.complete(prompt, { ...configOptions, ...opts }), retryOpts)
1272
1688
  };
1273
1689
  const activeTasks = Object.entries(tasks).filter(([, enabled]) => enabled).map(([name]) => name);
1274
- info3(`Running LLM tasks: ${activeTasks.join(", ")}`);
1690
+ info(`Running LLM tasks: ${activeTasks.join(", ")}`);
1275
1691
  if (tasks.enhance && tasks.categorize) {
1276
- info3("Enhancing and categorizing entries with LLM...");
1692
+ info("Enhancing and categorizing entries with LLM...");
1277
1693
  const result = await enhanceAndCategorize(provider, context.entries, llmContext);
1278
1694
  enhanced.entries = result.enhancedEntries;
1279
- enhanced.categories = {};
1280
- for (const cat of result.categories) {
1281
- enhanced.categories[cat.category] = cat.entries;
1282
- }
1283
- info3(`Enhanced ${enhanced.entries.length} entries into ${result.categories.length} categories`);
1695
+ enhanced.categories = buildOrderedCategories(result.categories, llmContext.categories);
1696
+ info(`Enhanced ${enhanced.entries.length} entries into ${result.categories.length} categories`);
1284
1697
  } else {
1285
1698
  if (tasks.enhance) {
1286
- info3("Enhancing entries with LLM...");
1699
+ info("Enhancing entries with LLM...");
1287
1700
  enhanced.entries = await enhanceEntries(provider, context.entries, llmContext, config.llm.concurrency);
1288
- info3(`Enhanced ${enhanced.entries.length} entries`);
1701
+ info(`Enhanced ${enhanced.entries.length} entries`);
1289
1702
  }
1290
1703
  if (tasks.categorize) {
1291
- info3("Categorizing entries with LLM...");
1704
+ info("Categorizing entries with LLM...");
1292
1705
  const categorized = await categorizeEntries(provider, enhanced.entries, llmContext);
1293
- enhanced.categories = {};
1294
- for (const cat of categorized) {
1295
- enhanced.categories[cat.category] = cat.entries;
1296
- }
1297
- info3(`Created ${categorized.length} categories`);
1706
+ enhanced.categories = buildOrderedCategories(categorized, llmContext.categories);
1707
+ info(`Created ${categorized.length} categories`);
1298
1708
  }
1299
1709
  }
1300
1710
  if (tasks.summarize) {
1301
- info3("Summarizing entries with LLM...");
1711
+ info("Summarizing entries with LLM...");
1302
1712
  enhanced.summary = await summarizeEntries(provider, enhanced.entries, llmContext);
1303
1713
  if (enhanced.summary) {
1304
- info3("Summary generated successfully");
1305
- debug2(`Summary: ${enhanced.summary.substring(0, 100)}...`);
1714
+ info("Summary generated successfully");
1715
+ debug(`Summary: ${enhanced.summary.substring(0, 100)}...`);
1306
1716
  } else {
1307
- warn3("Summary generation returned empty result");
1717
+ warn("Summary generation returned empty result");
1308
1718
  }
1309
1719
  }
1310
1720
  if (tasks.releaseNotes) {
1311
- info3("Generating release notes with LLM...");
1721
+ info("Generating release notes with LLM...");
1312
1722
  enhanced.releaseNotes = await generateReleaseNotes(provider, enhanced.entries, llmContext);
1313
1723
  if (enhanced.releaseNotes) {
1314
- info3("Release notes generated successfully");
1724
+ info("Release notes generated successfully");
1315
1725
  } else {
1316
- warn3("Release notes generation returned empty result");
1726
+ warn("Release notes generation returned empty result");
1317
1727
  }
1318
1728
  }
1319
1729
  return {
@@ -1321,8 +1731,8 @@ async function processWithLLM(context, config) {
1321
1731
  enhanced
1322
1732
  };
1323
1733
  } catch (error) {
1324
- warn3(`LLM processing failed: ${error instanceof Error ? error.message : String(error)}`);
1325
- warn3("Falling back to raw entries");
1734
+ warn(`LLM processing failed: ${error instanceof Error ? error.message : String(error)}`);
1735
+ warn("Falling back to raw entries");
1326
1736
  return context;
1327
1737
  }
1328
1738
  }
@@ -1330,17 +1740,17 @@ function getBuiltinTemplatePath(style) {
1330
1740
  let packageRoot;
1331
1741
  try {
1332
1742
  const currentUrl = import.meta.url;
1333
- packageRoot = path5.dirname(new URL(currentUrl).pathname);
1334
- packageRoot = path5.join(packageRoot, "..", "..");
1743
+ packageRoot = path8.dirname(new URL(currentUrl).pathname);
1744
+ packageRoot = path8.join(packageRoot, "..", "..");
1335
1745
  } catch {
1336
1746
  packageRoot = __dirname;
1337
1747
  }
1338
- return path5.join(packageRoot, "templates", style);
1748
+ return path8.join(packageRoot, "templates", style);
1339
1749
  }
1340
1750
  async function generateWithTemplate(contexts, config, outputPath, dryRun) {
1341
1751
  let templatePath;
1342
1752
  if (config.templates?.path) {
1343
- templatePath = path5.resolve(config.templates.path);
1753
+ templatePath = path8.resolve(config.templates.path);
1344
1754
  } else {
1345
1755
  templatePath = getBuiltinTemplatePath("keep-a-changelog");
1346
1756
  }
@@ -1350,79 +1760,83 @@ async function generateWithTemplate(contexts, config, outputPath, dryRun) {
1350
1760
  );
1351
1761
  const result = renderTemplate(templatePath, documentContext, config.templates?.engine);
1352
1762
  if (dryRun) {
1353
- info3(`Would write templated output to ${outputPath}`);
1354
- debug2("--- Changelog Preview ---");
1355
- debug2(result.content);
1356
- debug2("--- End Preview ---");
1763
+ info(`[DRY RUN] Changelog preview (would write to ${outputPath}):`);
1764
+ info(result.content);
1357
1765
  return;
1358
1766
  }
1359
1767
  if (outputPath === "-") {
1360
1768
  process.stdout.write(result.content);
1361
1769
  return;
1362
1770
  }
1363
- const dir = path5.dirname(outputPath);
1364
- if (!fs7.existsSync(dir)) {
1365
- fs7.mkdirSync(dir, { recursive: true });
1771
+ const dir = path8.dirname(outputPath);
1772
+ if (!fs10.existsSync(dir)) {
1773
+ fs10.mkdirSync(dir, { recursive: true });
1366
1774
  }
1367
- fs7.writeFileSync(outputPath, result.content, "utf-8");
1368
- success3(`Changelog written to ${outputPath} (using ${result.engine} template)`);
1775
+ fs10.writeFileSync(outputPath, result.content, "utf-8");
1776
+ const label = /changelog/i.test(outputPath) ? "Changelog" : "Release notes";
1777
+ success(`${label} written to ${outputPath} (using ${result.engine} template)`);
1369
1778
  }
1370
1779
  async function runPipeline(input, config, dryRun) {
1371
- debug2(`Processing ${input.packages.length} package(s)`);
1780
+ debug(`Processing ${input.packages.length} package(s)`);
1372
1781
  let contexts = input.packages.map(createTemplateContext);
1373
1782
  if (config.llm && !process.env.CHANGELOG_NO_LLM) {
1374
- info3("Processing with LLM enhancement");
1783
+ info("Processing with LLM enhancement");
1375
1784
  contexts = await Promise.all(contexts.map((ctx) => processWithLLM(ctx, config)));
1376
1785
  }
1377
1786
  const files = [];
1787
+ const fmtOpts = {
1788
+ includePackageName: contexts.length > 1 || contexts.some((c) => c.packageName.includes("/"))
1789
+ };
1378
1790
  for (const output of config.output) {
1379
- const outputLabel = output.file ? `${output.format} output \u2192 ${output.file}` : `${output.format} output`;
1380
- info3(`Generating ${outputLabel}`);
1791
+ const file = output.file ?? (output.format === "json" ? "changelog.json" : "CHANGELOG.md");
1792
+ const isChangelog = /changelog/i.test(file);
1793
+ const outputKind = isChangelog ? "changelog" : "release notes";
1794
+ info(`Generating ${outputKind} \u2192 ${file}`);
1381
1795
  switch (output.format) {
1382
1796
  case "markdown": {
1383
- const file = output.file ?? "CHANGELOG.md";
1797
+ const file2 = output.file ?? "CHANGELOG.md";
1384
1798
  try {
1385
1799
  const effectiveTemplateConfig = output.templates ?? config.templates;
1386
1800
  if (effectiveTemplateConfig?.path || output.options?.template) {
1387
1801
  const configWithTemplate = { ...config, templates: effectiveTemplateConfig };
1388
- await generateWithTemplate(contexts, configWithTemplate, file, dryRun);
1802
+ await generateWithTemplate(contexts, configWithTemplate, file2, dryRun);
1389
1803
  } else {
1390
- writeMarkdown(file, contexts, config, dryRun);
1804
+ writeMarkdown(file2, contexts, config, dryRun, fmtOpts);
1391
1805
  }
1392
- if (!dryRun) files.push(file);
1806
+ if (!dryRun) files.push(file2);
1393
1807
  } catch (error) {
1394
- warn3(`Failed to write ${file}: ${error instanceof Error ? error.message : String(error)}`);
1808
+ warn(`Failed to write ${file2}: ${error instanceof Error ? error.message : String(error)}`);
1395
1809
  }
1396
1810
  break;
1397
1811
  }
1398
1812
  case "json": {
1399
- const file = output.file ?? "changelog.json";
1813
+ const file2 = output.file ?? "changelog.json";
1400
1814
  try {
1401
- writeJson(file, contexts, dryRun);
1402
- if (!dryRun) files.push(file);
1815
+ writeJson(file2, contexts, dryRun);
1816
+ if (!dryRun) files.push(file2);
1403
1817
  } catch (error) {
1404
- warn3(`Failed to write ${file}: ${error instanceof Error ? error.message : String(error)}`);
1818
+ warn(`Failed to write ${file2}: ${error instanceof Error ? error.message : String(error)}`);
1405
1819
  }
1406
1820
  break;
1407
1821
  }
1408
1822
  case "github-release": {
1409
1823
  if (dryRun) {
1410
- info3("[DRY RUN] Would create GitHub release");
1824
+ info("[DRY RUN] Would create GitHub release");
1411
1825
  break;
1412
1826
  }
1413
1827
  const firstContext = contexts[0];
1414
1828
  if (!firstContext) {
1415
- warn3("No context available for GitHub release");
1829
+ warn("No context available for GitHub release");
1416
1830
  break;
1417
1831
  }
1418
1832
  const repoUrl = firstContext.repoUrl;
1419
1833
  if (!repoUrl) {
1420
- warn3("No repo URL available, cannot create GitHub release");
1834
+ warn("No repo URL available, cannot create GitHub release");
1421
1835
  break;
1422
1836
  }
1423
1837
  const parsed = parseRepoUrl(repoUrl);
1424
1838
  if (!parsed) {
1425
- warn3(`Could not parse repo URL: ${repoUrl}`);
1839
+ warn(`Could not parse repo URL: ${repoUrl}`);
1426
1840
  break;
1427
1841
  }
1428
1842
  await createGitHubRelease(firstContext, {
@@ -1436,7 +1850,7 @@ async function runPipeline(input, config, dryRun) {
1436
1850
  }
1437
1851
  }
1438
1852
  if (config.monorepo?.mode) {
1439
- const { detectMonorepo, writeMonorepoChangelogs } = await import("./aggregator-JZ3VUZKP.js");
1853
+ const { detectMonorepo, writeMonorepoChangelogs } = await import("./aggregator-XJ2EILO3.js");
1440
1854
  const cwd = process.cwd();
1441
1855
  const detected = detectMonorepo(cwd);
1442
1856
  if (detected.isMonorepo) {
@@ -1460,26 +1874,25 @@ async function runPipeline(input, config, dryRun) {
1460
1874
  return { packageNotes, files };
1461
1875
  }
1462
1876
  async function processInput(inputJson, config, dryRun) {
1463
- const input = parsePackageVersioner(inputJson);
1877
+ const input = parseVersionOutput(inputJson);
1464
1878
  return runPipeline(input, config, dryRun);
1465
1879
  }
1466
1880
 
1467
1881
  export {
1468
1882
  loadAuth,
1469
1883
  saveAuth,
1470
- loadConfig,
1884
+ loadConfig2 as loadConfig,
1471
1885
  getDefaultConfig,
1472
1886
  NotesError,
1473
1887
  InputParseError,
1474
1888
  TemplateError,
1475
1889
  LLMError,
1476
1890
  GitHubError,
1477
- ConfigError,
1891
+ ConfigError2 as ConfigError,
1478
1892
  getExitCode,
1479
- EXIT_CODES2 as EXIT_CODES,
1480
- parsePackageVersioner,
1481
- parsePackageVersionerFile,
1482
- parsePackageVersionerStdin,
1893
+ parseVersionOutput,
1894
+ parseVersionOutputFile,
1895
+ parseVersionOutputStdin,
1483
1896
  renderJson,
1484
1897
  writeJson,
1485
1898
  createTemplateContext,