@eldrforge/kodrdriv 0.0.19 → 0.0.24

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.
Files changed (64) hide show
  1. package/dist/arguments.js +664 -0
  2. package/dist/arguments.js.map +1 -0
  3. package/dist/commands/audio-commit.js +99 -0
  4. package/dist/commands/audio-commit.js.map +1 -0
  5. package/dist/commands/audio-review.js +110 -0
  6. package/dist/commands/audio-review.js.map +1 -0
  7. package/dist/commands/clean.js +36 -0
  8. package/dist/commands/clean.js.map +1 -0
  9. package/dist/commands/commit.js +125 -0
  10. package/dist/commands/commit.js.map +1 -0
  11. package/dist/commands/link.js +184 -0
  12. package/dist/commands/link.js.map +1 -0
  13. package/dist/commands/publish.js +301 -0
  14. package/dist/commands/publish.js.map +1 -0
  15. package/dist/commands/release.js +85 -0
  16. package/dist/commands/release.js.map +1 -0
  17. package/dist/commands/review.js +268 -0
  18. package/dist/commands/review.js.map +1 -0
  19. package/dist/commands/select-audio.js +29 -0
  20. package/dist/commands/select-audio.js.map +1 -0
  21. package/dist/commands/unlink.js +180 -0
  22. package/dist/commands/unlink.js.map +1 -0
  23. package/dist/constants.js +154 -0
  24. package/dist/constants.js.map +1 -0
  25. package/dist/content/diff.js +220 -0
  26. package/dist/content/diff.js.map +1 -0
  27. package/dist/content/issues.js +360 -0
  28. package/dist/content/issues.js.map +1 -0
  29. package/dist/content/log.js +53 -0
  30. package/dist/content/log.js.map +1 -0
  31. package/dist/content/releaseNotes.js +90 -0
  32. package/dist/content/releaseNotes.js.map +1 -0
  33. package/dist/error/ExitError.js +9 -0
  34. package/dist/error/ExitError.js.map +1 -0
  35. package/dist/logging.js +103 -0
  36. package/dist/logging.js.map +1 -0
  37. package/dist/main.js +30 -3707
  38. package/dist/main.js.map +1 -1
  39. package/dist/prompt/commit.js +56 -0
  40. package/dist/prompt/commit.js.map +1 -0
  41. package/dist/prompt/release.js +52 -0
  42. package/dist/prompt/release.js.map +1 -0
  43. package/dist/prompt/review.js +64 -0
  44. package/dist/prompt/review.js.map +1 -0
  45. package/dist/types.js +88 -0
  46. package/dist/types.js.map +1 -0
  47. package/dist/util/child.js +23 -0
  48. package/dist/util/child.js.map +1 -0
  49. package/dist/util/general.js +96 -0
  50. package/dist/util/general.js.map +1 -0
  51. package/dist/util/github.js +208 -0
  52. package/dist/util/github.js.map +1 -0
  53. package/dist/util/openai.js +146 -0
  54. package/dist/util/openai.js.map +1 -0
  55. package/dist/util/stdin.js +101 -0
  56. package/dist/util/stdin.js.map +1 -0
  57. package/dist/util/storage.js +149 -0
  58. package/dist/util/storage.js.map +1 -0
  59. package/package.json +5 -5
  60. /package/dist/{src/prompt → prompt}/instructions/commit.md +0 -0
  61. /package/dist/{src/prompt → prompt}/instructions/release.md +0 -0
  62. /package/dist/{src/prompt → prompt}/instructions/review.md +0 -0
  63. /package/dist/{src/prompt → prompt}/personas/releaser.md +0 -0
  64. /package/dist/{src/prompt → prompt}/personas/you.md +0 -0
@@ -0,0 +1,664 @@
1
+ import { Command } from 'commander';
2
+ import { z } from 'zod';
3
+ import { PROGRAM_NAME, VERSION, KODRDRIV_DEFAULTS, ALLOWED_COMMANDS, DEFAULT_COMMAND } from './constants.js';
4
+ import { getLogger } from './logging.js';
5
+ import { create } from './util/storage.js';
6
+ import { readStdin } from './util/stdin.js';
7
+
8
+ z.object({
9
+ dryRun: z.boolean().optional(),
10
+ verbose: z.boolean().optional(),
11
+ debug: z.boolean().optional(),
12
+ overrides: z.boolean().optional(),
13
+ checkConfig: z.boolean().optional(),
14
+ initConfig: z.boolean().optional(),
15
+ model: z.string().optional(),
16
+ contextDirectories: z.array(z.string()).optional(),
17
+ configDir: z.string().optional(),
18
+ outputDir: z.string().optional(),
19
+ preferencesDir: z.string().optional(),
20
+ cached: z.boolean().optional(),
21
+ add: z.boolean().optional(),
22
+ sendit: z.boolean().optional(),
23
+ from: z.string().optional(),
24
+ to: z.string().optional(),
25
+ excludedPatterns: z.array(z.string()).optional(),
26
+ context: z.string().optional(),
27
+ note: z.string().optional(),
28
+ direction: z.string().optional(),
29
+ messageLimit: z.number().optional(),
30
+ mergeMethod: z.enum([
31
+ 'merge',
32
+ 'squash',
33
+ 'rebase'
34
+ ]).optional(),
35
+ scopeRoots: z.string().optional(),
36
+ workspaceFile: z.string().optional(),
37
+ includeCommitHistory: z.boolean().optional(),
38
+ includeRecentDiffs: z.boolean().optional(),
39
+ includeReleaseNotes: z.boolean().optional(),
40
+ includeGithubIssues: z.boolean().optional(),
41
+ commitHistoryLimit: z.number().optional(),
42
+ diffHistoryLimit: z.number().optional(),
43
+ releaseNotesLimit: z.number().optional(),
44
+ githubIssuesLimit: z.number().optional(),
45
+ file: z.string().optional(),
46
+ keepTemp: z.boolean().optional()
47
+ });
48
+ // Function to transform flat CLI args into nested Config structure
49
+ const transformCliArgs = (finalCliArgs)=>{
50
+ const transformedCliArgs = {};
51
+ // Direct mappings from Input to Config
52
+ if (finalCliArgs.dryRun !== undefined) transformedCliArgs.dryRun = finalCliArgs.dryRun;
53
+ if (finalCliArgs.verbose !== undefined) transformedCliArgs.verbose = finalCliArgs.verbose;
54
+ if (finalCliArgs.debug !== undefined) transformedCliArgs.debug = finalCliArgs.debug;
55
+ if (finalCliArgs.overrides !== undefined) transformedCliArgs.overrides = finalCliArgs.overrides;
56
+ if (finalCliArgs.model !== undefined) transformedCliArgs.model = finalCliArgs.model;
57
+ if (finalCliArgs.contextDirectories !== undefined) transformedCliArgs.contextDirectories = finalCliArgs.contextDirectories;
58
+ // Map configDir (CLI) to configDirectory (Cardigantime standard)
59
+ if (finalCliArgs.configDir !== undefined) transformedCliArgs.configDirectory = finalCliArgs.configDir;
60
+ // Map outputDir (CLI) to outputDirectory (Config standard)
61
+ if (finalCliArgs.outputDir !== undefined) transformedCliArgs.outputDirectory = finalCliArgs.outputDir;
62
+ // Map preferencesDir (CLI) to preferencesDirectory (Config standard)
63
+ if (finalCliArgs.preferencesDir !== undefined) transformedCliArgs.preferencesDirectory = finalCliArgs.preferencesDir;
64
+ // Nested mappings for 'commit' options
65
+ if (finalCliArgs.cached !== undefined || finalCliArgs.sendit !== undefined || finalCliArgs.add !== undefined) {
66
+ transformedCliArgs.commit = {};
67
+ if (finalCliArgs.add !== undefined) transformedCliArgs.commit.add = finalCliArgs.add;
68
+ if (finalCliArgs.cached !== undefined) transformedCliArgs.commit.cached = finalCliArgs.cached;
69
+ if (finalCliArgs.sendit !== undefined) transformedCliArgs.commit.sendit = finalCliArgs.sendit;
70
+ if (finalCliArgs.messageLimit !== undefined) transformedCliArgs.commit.messageLimit = finalCliArgs.messageLimit;
71
+ if (finalCliArgs.context !== undefined) transformedCliArgs.commit.context = finalCliArgs.context;
72
+ if (finalCliArgs.direction !== undefined) transformedCliArgs.commit.direction = finalCliArgs.direction;
73
+ }
74
+ // Nested mappings for 'audioCommit' options
75
+ if (finalCliArgs.file !== undefined || finalCliArgs.keepTemp !== undefined) {
76
+ transformedCliArgs.audioCommit = {};
77
+ if (finalCliArgs.file !== undefined) transformedCliArgs.audioCommit.file = finalCliArgs.file;
78
+ if (finalCliArgs.keepTemp !== undefined) transformedCliArgs.audioCommit.keepTemp = finalCliArgs.keepTemp;
79
+ }
80
+ // Nested mappings for 'release' options
81
+ if (finalCliArgs.from !== undefined || finalCliArgs.to !== undefined) {
82
+ transformedCliArgs.release = {};
83
+ if (finalCliArgs.from !== undefined) transformedCliArgs.release.from = finalCliArgs.from;
84
+ if (finalCliArgs.to !== undefined) transformedCliArgs.release.to = finalCliArgs.to;
85
+ if (finalCliArgs.context !== undefined) transformedCliArgs.release.context = finalCliArgs.context;
86
+ if (finalCliArgs.messageLimit !== undefined) transformedCliArgs.release.messageLimit = finalCliArgs.messageLimit;
87
+ }
88
+ // Nested mappings for 'publish' options
89
+ if (finalCliArgs.mergeMethod !== undefined) {
90
+ transformedCliArgs.publish = {};
91
+ if (finalCliArgs.mergeMethod !== undefined) transformedCliArgs.publish.mergeMethod = finalCliArgs.mergeMethod;
92
+ }
93
+ // Nested mappings for 'link' and 'unlink' options (both use the same configuration)
94
+ if (finalCliArgs.scopeRoots !== undefined || finalCliArgs.workspaceFile !== undefined) {
95
+ transformedCliArgs.link = {};
96
+ if (finalCliArgs.scopeRoots !== undefined) {
97
+ try {
98
+ transformedCliArgs.link.scopeRoots = JSON.parse(finalCliArgs.scopeRoots);
99
+ } catch (error) {
100
+ throw new Error(`Invalid JSON for scope-roots: ${finalCliArgs.scopeRoots}`);
101
+ }
102
+ }
103
+ if (finalCliArgs.workspaceFile !== undefined) transformedCliArgs.link.workspaceFile = finalCliArgs.workspaceFile;
104
+ }
105
+ // Nested mappings for 'audio-review' options
106
+ if (finalCliArgs.includeCommitHistory !== undefined || finalCliArgs.includeRecentDiffs !== undefined || finalCliArgs.includeReleaseNotes !== undefined || finalCliArgs.includeGithubIssues !== undefined || finalCliArgs.commitHistoryLimit !== undefined || finalCliArgs.diffHistoryLimit !== undefined || finalCliArgs.releaseNotesLimit !== undefined || finalCliArgs.githubIssuesLimit !== undefined || finalCliArgs.file !== undefined || finalCliArgs.keepTemp !== undefined) {
107
+ transformedCliArgs.audioReview = {};
108
+ if (finalCliArgs.includeCommitHistory !== undefined) transformedCliArgs.audioReview.includeCommitHistory = finalCliArgs.includeCommitHistory;
109
+ if (finalCliArgs.includeRecentDiffs !== undefined) transformedCliArgs.audioReview.includeRecentDiffs = finalCliArgs.includeRecentDiffs;
110
+ if (finalCliArgs.includeReleaseNotes !== undefined) transformedCliArgs.audioReview.includeReleaseNotes = finalCliArgs.includeReleaseNotes;
111
+ if (finalCliArgs.includeGithubIssues !== undefined) transformedCliArgs.audioReview.includeGithubIssues = finalCliArgs.includeGithubIssues;
112
+ if (finalCliArgs.commitHistoryLimit !== undefined) transformedCliArgs.audioReview.commitHistoryLimit = finalCliArgs.commitHistoryLimit;
113
+ if (finalCliArgs.diffHistoryLimit !== undefined) transformedCliArgs.audioReview.diffHistoryLimit = finalCliArgs.diffHistoryLimit;
114
+ if (finalCliArgs.releaseNotesLimit !== undefined) transformedCliArgs.audioReview.releaseNotesLimit = finalCliArgs.releaseNotesLimit;
115
+ if (finalCliArgs.githubIssuesLimit !== undefined) transformedCliArgs.audioReview.githubIssuesLimit = finalCliArgs.githubIssuesLimit;
116
+ if (finalCliArgs.context !== undefined) transformedCliArgs.audioReview.context = finalCliArgs.context;
117
+ if (finalCliArgs.sendit !== undefined) transformedCliArgs.audioReview.sendit = finalCliArgs.sendit;
118
+ if (finalCliArgs.file !== undefined) transformedCliArgs.audioReview.file = finalCliArgs.file;
119
+ if (finalCliArgs.keepTemp !== undefined) transformedCliArgs.audioReview.keepTemp = finalCliArgs.keepTemp;
120
+ }
121
+ // Nested mappings for 'review' options
122
+ if (finalCliArgs.includeCommitHistory !== undefined || finalCliArgs.includeRecentDiffs !== undefined || finalCliArgs.includeReleaseNotes !== undefined || finalCliArgs.includeGithubIssues !== undefined || finalCliArgs.commitHistoryLimit !== undefined || finalCliArgs.diffHistoryLimit !== undefined || finalCliArgs.releaseNotesLimit !== undefined || finalCliArgs.githubIssuesLimit !== undefined || finalCliArgs.context !== undefined || finalCliArgs.sendit !== undefined || finalCliArgs.note !== undefined) {
123
+ transformedCliArgs.review = {};
124
+ if (finalCliArgs.note !== undefined) transformedCliArgs.review.note = finalCliArgs.note;
125
+ // Include optional review configuration options if specified
126
+ if (finalCliArgs.includeCommitHistory !== undefined) transformedCliArgs.review.includeCommitHistory = finalCliArgs.includeCommitHistory;
127
+ if (finalCliArgs.includeRecentDiffs !== undefined) transformedCliArgs.review.includeRecentDiffs = finalCliArgs.includeRecentDiffs;
128
+ if (finalCliArgs.includeReleaseNotes !== undefined) transformedCliArgs.review.includeReleaseNotes = finalCliArgs.includeReleaseNotes;
129
+ if (finalCliArgs.includeGithubIssues !== undefined) transformedCliArgs.review.includeGithubIssues = finalCliArgs.includeGithubIssues;
130
+ if (finalCliArgs.commitHistoryLimit !== undefined) transformedCliArgs.review.commitHistoryLimit = finalCliArgs.commitHistoryLimit;
131
+ if (finalCliArgs.diffHistoryLimit !== undefined) transformedCliArgs.review.diffHistoryLimit = finalCliArgs.diffHistoryLimit;
132
+ if (finalCliArgs.releaseNotesLimit !== undefined) transformedCliArgs.review.releaseNotesLimit = finalCliArgs.releaseNotesLimit;
133
+ if (finalCliArgs.githubIssuesLimit !== undefined) transformedCliArgs.review.githubIssuesLimit = finalCliArgs.githubIssuesLimit;
134
+ if (finalCliArgs.context !== undefined) transformedCliArgs.review.context = finalCliArgs.context;
135
+ if (finalCliArgs.sendit !== undefined) transformedCliArgs.review.sendit = finalCliArgs.sendit;
136
+ }
137
+ if (finalCliArgs.excludedPatterns !== undefined) transformedCliArgs.excludedPatterns = finalCliArgs.excludedPatterns;
138
+ // Note: openaiApiKey is handled separately via environment variable only
139
+ return transformedCliArgs;
140
+ };
141
+ // Update configure signature to accept cardigantime
142
+ const configure = async (cardigantime)=>{
143
+ var _config_contextDirectories, _config_link;
144
+ const logger = getLogger();
145
+ let program = new Command();
146
+ // Configure program basics
147
+ program.name(PROGRAM_NAME).summary('Create Intelligent Release Notes or Change Logs from Git').description('Create Intelligent Release Notes or Change Logs from Git').version(VERSION);
148
+ // Let cardigantime add its arguments first
149
+ program = await cardigantime.configure(program);
150
+ // Check if --check-config is in process.argv early
151
+ if (process.argv.includes('--check-config')) {
152
+ // For check-config, use CardiganTime's built-in checkConfig method
153
+ program.parse();
154
+ const cliArgs = program.opts();
155
+ // Transform the flat CLI args
156
+ const transformedCliArgs = transformCliArgs(cliArgs);
157
+ // Use CardiganTime's built-in checkConfig method which displays
158
+ // hierarchical configuration information in a well-formatted way
159
+ await cardigantime.checkConfig(transformedCliArgs);
160
+ // Return minimal config for consistency, but main processing is done
161
+ const config = await validateAndProcessOptions({});
162
+ const secureConfig = await validateAndProcessSecureOptions();
163
+ const commandConfig = {
164
+ commandName: 'check-config'
165
+ };
166
+ return [
167
+ config,
168
+ secureConfig,
169
+ commandConfig
170
+ ];
171
+ }
172
+ // Check if --init-config is in process.argv early
173
+ if (process.argv.includes('--init-config')) {
174
+ // For init-config, use CardiganTime's built-in generateConfig method
175
+ program.parse();
176
+ const cliArgs = program.opts();
177
+ // Transform the flat CLI args
178
+ const transformedCliArgs = transformCliArgs(cliArgs);
179
+ // Use CardiganTime's built-in generateConfig method
180
+ await cardigantime.generateConfig(transformedCliArgs.configDirectory || KODRDRIV_DEFAULTS.configDirectory);
181
+ // Return minimal config for consistency, but main processing is done
182
+ const config = await validateAndProcessOptions({});
183
+ const secureConfig = await validateAndProcessSecureOptions();
184
+ const commandConfig = {
185
+ commandName: 'init-config'
186
+ };
187
+ return [
188
+ config,
189
+ secureConfig,
190
+ commandConfig
191
+ ];
192
+ }
193
+ // Get CLI arguments using the new function
194
+ const [finalCliArgs, commandConfig] = await getCliConfig(program);
195
+ logger.silly('Loaded Command Line Options: %s', JSON.stringify(finalCliArgs, null, 2));
196
+ // Transform the flat CLI args using the new function
197
+ const transformedCliArgs = transformCliArgs(finalCliArgs);
198
+ logger.silly('Transformed CLI Args for merging: %s', JSON.stringify(transformedCliArgs, null, 2));
199
+ // Get values from config file using Cardigantime's hierarchical configuration
200
+ const fileValues = await cardigantime.read(transformedCliArgs);
201
+ // Merge configurations: Defaults -> File -> CLI
202
+ // Properly merge the link section to preserve scope roots from config file
203
+ const mergedLink = {
204
+ ...KODRDRIV_DEFAULTS.link,
205
+ ...fileValues.link,
206
+ ...transformedCliArgs.link
207
+ };
208
+ const partialConfig = {
209
+ ...KODRDRIV_DEFAULTS,
210
+ ...fileValues,
211
+ ...transformedCliArgs,
212
+ link: mergedLink
213
+ }; // Cast to Partial<Config> initially
214
+ // Specific validation and processing after merge
215
+ const config = await validateAndProcessOptions(partialConfig);
216
+ // Log effective configuration summary at verbose level
217
+ logger.verbose('Configuration complete. Effective settings:');
218
+ logger.verbose(` Command: ${commandConfig.commandName}`);
219
+ logger.verbose(` Model: ${config.model}`);
220
+ logger.verbose(` Dry run: ${config.dryRun}`);
221
+ logger.verbose(` Debug: ${config.debug}`);
222
+ logger.verbose(` Verbose: ${config.verbose}`);
223
+ logger.verbose(` Config directory: ${config.configDirectory}`);
224
+ logger.verbose(` Output directory: ${config.outputDirectory}`);
225
+ logger.verbose(` Context directories: ${((_config_contextDirectories = config.contextDirectories) === null || _config_contextDirectories === void 0 ? void 0 : _config_contextDirectories.join(', ')) || 'none'}`);
226
+ if (config.excludedPatterns && config.excludedPatterns.length > 0) {
227
+ logger.verbose(` Excluded patterns: ${config.excludedPatterns.join(', ')}`);
228
+ }
229
+ if (Object.keys(((_config_link = config.link) === null || _config_link === void 0 ? void 0 : _config_link.scopeRoots) || {}).length > 0) {
230
+ logger.verbose(` Link scope roots: ${Object.keys(config.link.scopeRoots).join(', ')}`);
231
+ }
232
+ logger.silly('Final configuration: %s', JSON.stringify(config, null, 2));
233
+ const secureConfig = await validateAndProcessSecureOptions();
234
+ return [
235
+ config,
236
+ secureConfig,
237
+ commandConfig
238
+ ];
239
+ };
240
+ // Function to handle CLI argument parsing and processing
241
+ async function getCliConfig(program) {
242
+ const addSharedOptions = (command)=>{
243
+ command.option('--dry-run', 'perform a dry run without saving files') // Removed default, will be handled by merging
244
+ .option('--verbose', 'enable verbose logging').option('--debug', 'enable debug logging').option('--overrides', 'enable overrides').option('--model <model>', 'OpenAI model to use').option('-d, --context-directories [contextDirectories...]', 'directories to scan for context').option('--config-dir <configDir>', 'configuration directory') // Keep config-dir for specifying location
245
+ .option('--output-dir <outputDir>', 'output directory for generated files').option('--preferences-dir <preferencesDir>', 'preferences directory for personal settings').option('--excluded-paths [excludedPatterns...]', 'paths to exclude from the diff').option('--keep-temp', 'keep temporary recording files');
246
+ };
247
+ // Add global options to the main program
248
+ // (cardigantime already adds most global options like --verbose, --debug, --config-dir)
249
+ // Add subcommands
250
+ const commitCommand = program.command('commit').argument('[direction]', 'direction or guidance for the commit message').description('Generate commit notes').option('--context <context>', 'context for the commit message').option('--cached', 'use cached diff').option('--add', 'add all changes before committing').option('--sendit', 'Commit with the message generated. No review.').option('--message-limit <messageLimit>', 'limit the number of messages to generate');
251
+ // Add shared options to commit command
252
+ addSharedOptions(commitCommand);
253
+ // Customize help output for commit command
254
+ commitCommand.configureHelp({
255
+ formatHelp: (cmd, helper)=>{
256
+ const nameAndVersion = `${helper.commandUsage(cmd)}\n\n${helper.commandDescription(cmd)}\n`;
257
+ const commitOptions = [
258
+ [
259
+ '--context <context>',
260
+ 'context for the commit message'
261
+ ]
262
+ ];
263
+ const behavioralOptions = [
264
+ [
265
+ '--cached',
266
+ 'use cached diff'
267
+ ],
268
+ [
269
+ '--add',
270
+ 'add all changes before committing'
271
+ ],
272
+ [
273
+ '--sendit',
274
+ 'Commit with the message generated. No review.'
275
+ ],
276
+ [
277
+ '--message-limit <messageLimit>',
278
+ 'limit the number of messages to generate'
279
+ ]
280
+ ];
281
+ const globalOptions = [
282
+ [
283
+ '--dry-run',
284
+ 'perform a dry run without saving files'
285
+ ],
286
+ [
287
+ '--verbose',
288
+ 'enable verbose logging'
289
+ ],
290
+ [
291
+ '--debug',
292
+ 'enable debug logging'
293
+ ],
294
+ [
295
+ '--overrides',
296
+ 'enable overrides'
297
+ ],
298
+ [
299
+ '--model <model>',
300
+ 'OpenAI model to use'
301
+ ],
302
+ [
303
+ '-d, --context-directories [contextDirectories...]',
304
+ 'directories to scan for context'
305
+ ],
306
+ [
307
+ '--config-dir <configDir>',
308
+ 'configuration directory'
309
+ ],
310
+ [
311
+ '--excluded-paths [excludedPatterns...]',
312
+ 'paths to exclude from the diff'
313
+ ],
314
+ [
315
+ '-h, --help',
316
+ 'display help for command'
317
+ ]
318
+ ];
319
+ const formatOptionsSection = (title, options)=>{
320
+ const maxWidth = Math.max(...options.map(([flag])=>flag.length));
321
+ return `${title}:\n` + options.map(([flag, desc])=>` ${flag.padEnd(maxWidth + 2)} ${desc}`).join('\n') + '\n';
322
+ };
323
+ return nameAndVersion + '\n' + formatOptionsSection('Commit Message Options', commitOptions) + '\n' + formatOptionsSection('Behavioral Options', behavioralOptions) + '\n' + formatOptionsSection('Global Options', globalOptions) + '\n' + 'Environment Variables:\n' + ' OPENAI_API_KEY OpenAI API key (required)\n';
324
+ }
325
+ });
326
+ const audioCommitCommand = program.command('audio-commit').option('--cached', 'use cached diff').option('--add', 'add all changes before committing').option('--sendit', 'Commit with the message generated. No review.').option('--direction <direction>', 'direction or guidance for the commit message').option('--message-limit <messageLimit>', 'limit the number of messages to generate').option('--file <file>', 'audio file path').description('Record audio to provide context, then generate and optionally commit with AI-generated message');
327
+ addSharedOptions(audioCommitCommand);
328
+ const releaseCommand = program.command('release').option('--from <from>', 'branch to generate release notes from').option('--to <to>', 'branch to generate release notes to').option('--context <context>', 'context for the commit message').description('Generate release notes');
329
+ addSharedOptions(releaseCommand);
330
+ const publishCommand = program.command('publish').option('--merge-method <method>', 'method to merge PR (merge, squash, rebase)', 'squash').description('Publish a release');
331
+ addSharedOptions(publishCommand);
332
+ const linkCommand = program.command('link').option('--scope-roots <scopeRoots>', 'JSON mapping of scopes to root directories (e.g., \'{"@company": "../"}\')').option('--workspace-file <workspaceFile>', 'path to workspace file', 'pnpm-workspace.yaml').description('Manage pnpm workspace links for local development');
333
+ addSharedOptions(linkCommand);
334
+ const unlinkCommand = program.command('unlink').option('--scope-roots <scopeRoots>', 'JSON mapping of scopes to root directories (e.g., \'{"@company": "../"}\')').option('--workspace-file <workspaceFile>', 'path to workspace file', 'pnpm-workspace.yaml').description('Remove pnpm workspace links and rebuild dependencies');
335
+ addSharedOptions(unlinkCommand);
336
+ const audioReviewCommand = program.command('audio-review').option('--include-commit-history', 'include recent commit log messages in context (default: true)').option('--no-include-commit-history', 'exclude commit log messages from context').option('--include-recent-diffs', 'include recent commit diffs in context (default: true)').option('--no-include-recent-diffs', 'exclude recent diffs from context').option('--include-release-notes', 'include recent release notes in context (default: false)').option('--no-include-release-notes', 'exclude release notes from context').option('--include-github-issues', 'include open GitHub issues in context (default: true)').option('--no-include-github-issues', 'exclude GitHub issues from context').option('--commit-history-limit <limit>', 'number of recent commits to include', parseInt).option('--diff-history-limit <limit>', 'number of recent commit diffs to include', parseInt).option('--release-notes-limit <limit>', 'number of recent release notes to include', parseInt).option('--github-issues-limit <limit>', 'number of open GitHub issues to include (max 20)', parseInt).option('--context <context>', 'additional context for the audio review').option('--file <file>', 'audio file path').description('Record audio, transcribe with Whisper, and analyze for project issues using AI');
337
+ addSharedOptions(audioReviewCommand);
338
+ const reviewCommand = program.command('review').argument('[note]', 'review note to analyze for project issues').option('--include-commit-history', 'include recent commit log messages in context (default: true)').option('--no-include-commit-history', 'exclude commit log messages from context').option('--include-recent-diffs', 'include recent commit diffs in context (default: true)').option('--no-include-recent-diffs', 'exclude recent diffs from context').option('--include-release-notes', 'include recent release notes in context (default: false)').option('--no-include-release-notes', 'exclude release notes from context').option('--include-github-issues', 'include open GitHub issues in context (default: true)').option('--no-include-github-issues', 'exclude GitHub issues from context').option('--commit-history-limit <limit>', 'number of recent commits to include', parseInt).option('--diff-history-limit <limit>', 'number of recent commit diffs to include', parseInt).option('--release-notes-limit <limit>', 'number of recent release notes to include', parseInt).option('--github-issues-limit <limit>', 'number of open GitHub issues to include (max 20)', parseInt).option('--context <context>', 'additional context for the review').option('--sendit', 'Create GitHub issues automatically without confirmation').description('Analyze review note for project issues using AI');
339
+ addSharedOptions(reviewCommand);
340
+ // Customize help output for review command
341
+ reviewCommand.configureHelp({
342
+ formatHelp: (cmd, helper)=>{
343
+ const nameAndVersion = `kodrdriv review [note] [options]\n\nAnalyze review note for project issues using AI\n`;
344
+ const argumentsSection = [
345
+ [
346
+ 'note',
347
+ 'review note to analyze for project issues (can also be piped via STDIN)'
348
+ ]
349
+ ];
350
+ const reviewOptions = [
351
+ [
352
+ '--context <context>',
353
+ 'additional context for the review'
354
+ ]
355
+ ];
356
+ const gitContextOptions = [
357
+ [
358
+ '--include-commit-history',
359
+ 'include recent commit log messages in context (default: true)'
360
+ ],
361
+ [
362
+ '--no-include-commit-history',
363
+ 'exclude commit log messages from context'
364
+ ],
365
+ [
366
+ '--include-recent-diffs',
367
+ 'include recent commit diffs in context (default: true)'
368
+ ],
369
+ [
370
+ '--no-include-recent-diffs',
371
+ 'exclude recent diffs from context'
372
+ ],
373
+ [
374
+ '--include-release-notes',
375
+ 'include recent release notes in context (default: false)'
376
+ ],
377
+ [
378
+ '--no-include-release-notes',
379
+ 'exclude release notes from context'
380
+ ],
381
+ [
382
+ '--include-github-issues',
383
+ 'include open GitHub issues in context (default: true)'
384
+ ],
385
+ [
386
+ '--no-include-github-issues',
387
+ 'exclude GitHub issues from context'
388
+ ],
389
+ [
390
+ '--commit-history-limit <limit>',
391
+ 'number of recent commits to include'
392
+ ],
393
+ [
394
+ '--diff-history-limit <limit>',
395
+ 'number of recent commit diffs to include'
396
+ ],
397
+ [
398
+ '--release-notes-limit <limit>',
399
+ 'number of recent release notes to include'
400
+ ],
401
+ [
402
+ '--github-issues-limit <limit>',
403
+ 'number of open GitHub issues to include (max 20)'
404
+ ]
405
+ ];
406
+ const behavioralOptions = [
407
+ [
408
+ '--sendit',
409
+ 'Create GitHub issues automatically without confirmation'
410
+ ]
411
+ ];
412
+ const globalOptions = [
413
+ [
414
+ '--dry-run',
415
+ 'perform a dry run without saving files'
416
+ ],
417
+ [
418
+ '--verbose',
419
+ 'enable verbose logging'
420
+ ],
421
+ [
422
+ '--debug',
423
+ 'enable debug logging'
424
+ ],
425
+ [
426
+ '--overrides',
427
+ 'enable overrides'
428
+ ],
429
+ [
430
+ '--model <model>',
431
+ 'OpenAI model to use'
432
+ ],
433
+ [
434
+ '-d, --context-directories [contextDirectories...]',
435
+ 'directories to scan for context'
436
+ ],
437
+ [
438
+ '--config-dir <configDir>',
439
+ 'configuration directory'
440
+ ],
441
+ [
442
+ '--output-dir <outputDir>',
443
+ 'output directory for generated files'
444
+ ],
445
+ [
446
+ '--excluded-paths [excludedPatterns...]',
447
+ 'paths to exclude from the diff'
448
+ ],
449
+ [
450
+ '-h, --help',
451
+ 'display help for command'
452
+ ]
453
+ ];
454
+ const formatOptionsSection = (title, options)=>{
455
+ const maxWidth = Math.max(...options.map(([flag])=>flag.length));
456
+ return `${title}:\n` + options.map(([flag, desc])=>` ${flag.padEnd(maxWidth + 2)} ${desc}`).join('\n') + '\n';
457
+ };
458
+ return nameAndVersion + '\n' + formatOptionsSection('Arguments', argumentsSection) + '\n' + formatOptionsSection('Options', reviewOptions) + '\n' + formatOptionsSection('Git Context Parameters', gitContextOptions) + '\n' + formatOptionsSection('Behavioral Options', behavioralOptions) + '\n' + formatOptionsSection('Global Options', globalOptions) + '\n' + 'Environment Variables:\n' + ' OPENAI_API_KEY OpenAI API key (required)\n';
459
+ }
460
+ });
461
+ const cleanCommand = program.command('clean').description('Remove the output directory and all generated files');
462
+ addSharedOptions(cleanCommand);
463
+ const selectAudioCommand = program.command('select-audio').description('Interactively select and save audio device for recording');
464
+ addSharedOptions(selectAudioCommand);
465
+ program.parse();
466
+ const cliArgs = program.opts(); // Get all opts initially
467
+ // Determine which command is being run
468
+ let commandName = DEFAULT_COMMAND;
469
+ let commandOptions = {}; // Store specific command options
470
+ if (program.args.length > 0) {
471
+ commandName = program.args[0];
472
+ validateCommand(commandName);
473
+ }
474
+ // Only proceed with command-specific options if validation passed
475
+ if (ALLOWED_COMMANDS.includes(commandName)) {
476
+ if (commandName === 'commit' && commitCommand.opts) {
477
+ commandOptions = commitCommand.opts();
478
+ // Handle positional argument for direction
479
+ const args = commitCommand.args;
480
+ if (args && args.length > 0 && args[0]) {
481
+ commandOptions.direction = args[0];
482
+ }
483
+ // Check for STDIN input for direction (takes precedence over positional argument)
484
+ const stdinInput = await readStdin();
485
+ if (stdinInput) {
486
+ commandOptions.direction = stdinInput;
487
+ }
488
+ } else if (commandName === 'audio-commit' && audioCommitCommand.opts) {
489
+ commandOptions = audioCommitCommand.opts();
490
+ } else if (commandName === 'release' && releaseCommand.opts) {
491
+ commandOptions = releaseCommand.opts();
492
+ } else if (commandName === 'publish' && publishCommand.opts) {
493
+ commandOptions = publishCommand.opts();
494
+ } else if (commandName === 'link' && linkCommand.opts) {
495
+ commandOptions = linkCommand.opts();
496
+ } else if (commandName === 'unlink' && unlinkCommand.opts) {
497
+ commandOptions = unlinkCommand.opts();
498
+ } else if (commandName === 'audio-review' && audioReviewCommand.opts) {
499
+ commandOptions = audioReviewCommand.opts();
500
+ } else if (commandName === 'review' && reviewCommand.opts) {
501
+ commandOptions = reviewCommand.opts();
502
+ // Handle positional argument for note
503
+ const args = reviewCommand.args;
504
+ if (args && args.length > 0 && args[0]) {
505
+ commandOptions.note = args[0];
506
+ }
507
+ // Check for STDIN input for note (takes precedence over positional argument)
508
+ const stdinInput = await readStdin();
509
+ if (stdinInput) {
510
+ commandOptions.note = stdinInput;
511
+ }
512
+ } else if (commandName === 'clean' && cleanCommand.opts) {
513
+ commandOptions = cleanCommand.opts();
514
+ } else if (commandName === 'select-audio' && selectAudioCommand.opts) {
515
+ commandOptions = selectAudioCommand.opts();
516
+ }
517
+ }
518
+ // Include command name in CLI args for merging
519
+ const finalCliArgs = {
520
+ ...cliArgs,
521
+ ...commandOptions
522
+ };
523
+ const commandConfig = {
524
+ commandName
525
+ };
526
+ return [
527
+ finalCliArgs,
528
+ commandConfig
529
+ ];
530
+ }
531
+ async function validateAndProcessSecureOptions() {
532
+ // For check-config and init-config commands, we don't want to throw an error for missing API key
533
+ const isCheckConfig = process.argv.includes('--check-config');
534
+ const isInitConfig = process.argv.includes('--init-config');
535
+ if (!process.env.OPENAI_API_KEY && !isCheckConfig && !isInitConfig) {
536
+ throw new Error('OpenAI API key is required. Please set the OPENAI_API_KEY environment variable.');
537
+ }
538
+ // Prefer CLI key if provided, otherwise use env var (might be undefined for check-config/init-config)
539
+ const openaiApiKey = process.env.OPENAI_API_KEY;
540
+ const secureConfig = {
541
+ openaiApiKey: openaiApiKey
542
+ };
543
+ return secureConfig;
544
+ }
545
+ // Renamed validation function to reflect its broader role
546
+ async function validateAndProcessOptions(options) {
547
+ var _options_commit, _options_commit1, _options_commit2, _options_commit3, _options_commit4, _options_commit5, _options_audioCommit, _options_audioCommit1, _options_audioCommit2, _options_audioCommit3, _options_release, _options_release1, _options_release2, _options_release3, _options_audioReview, _options_audioReview1, _options_audioReview2, _options_audioReview3, _options_audioReview4, _options_audioReview5, _options_audioReview6, _options_audioReview7, _options_audioReview8, _options_audioReview9, _options_audioReview10, _options_audioReview11, _options_audioReview12, _options_audioReview13, _options_review, _options_review1, _options_review2, _options_review3, _options_review4, _options_review5, _options_review6, _options_review7, _options_review8, _options_review9, _options_review10, _options_publish, _options_publish1, _options_publish2, _options_publish3, _options_publish4, _options_link, _options_link1, _options_link2;
548
+ const contextDirectories = await validateContextDirectories(options.contextDirectories || KODRDRIV_DEFAULTS.contextDirectories);
549
+ const configDir = options.configDirectory || KODRDRIV_DEFAULTS.configDirectory;
550
+ var _options_dryRun, _options_verbose, _options_debug, _options_overrides, _options_model, _options_outputDirectory, _options_preferencesDirectory, _options_discoveredConfigDirs, _options_resolvedConfigDirs, _options_commit_add, _options_commit_cached, _options_commit_sendit, _options_commit_messageLimit, _options_audioCommit_maxRecordingTime, _options_audioCommit_audioDevice, _options_release_from, _options_release_to, _options_release_messageLimit, _options_audioReview_includeCommitHistory, _options_audioReview_includeRecentDiffs, _options_audioReview_includeReleaseNotes, _options_audioReview_includeGithubIssues, _options_audioReview_commitHistoryLimit, _options_audioReview_diffHistoryLimit, _options_audioReview_releaseNotesLimit, _options_audioReview_githubIssuesLimit, _options_audioReview_sendit, _options_audioReview_maxRecordingTime, _options_audioReview_audioDevice, _options_review_includeCommitHistory, _options_review_includeRecentDiffs, _options_review_includeReleaseNotes, _options_review_includeGithubIssues, _options_review_commitHistoryLimit, _options_review_diffHistoryLimit, _options_review_releaseNotesLimit, _options_review_githubIssuesLimit, _options_review_sendit, _options_publish_mergeMethod, _options_publish_requiredEnvVars, _options_publish_linkWorkspacePackages, _options_publish_unlinkWorkspacePackages, _options_link_scopeRoots, _options_link_workspaceFile, _options_link_dryRun, _options_excludedPatterns;
551
+ // Skip config directory validation since Cardigantime handles hierarchical lookup
552
+ // Ensure all required fields are present and have correct types after merging
553
+ const finalConfig = {
554
+ dryRun: (_options_dryRun = options.dryRun) !== null && _options_dryRun !== void 0 ? _options_dryRun : KODRDRIV_DEFAULTS.dryRun,
555
+ verbose: (_options_verbose = options.verbose) !== null && _options_verbose !== void 0 ? _options_verbose : KODRDRIV_DEFAULTS.verbose,
556
+ debug: (_options_debug = options.debug) !== null && _options_debug !== void 0 ? _options_debug : KODRDRIV_DEFAULTS.debug,
557
+ overrides: (_options_overrides = options.overrides) !== null && _options_overrides !== void 0 ? _options_overrides : KODRDRIV_DEFAULTS.overrides,
558
+ model: (_options_model = options.model) !== null && _options_model !== void 0 ? _options_model : KODRDRIV_DEFAULTS.model,
559
+ contextDirectories: contextDirectories,
560
+ configDirectory: configDir,
561
+ outputDirectory: (_options_outputDirectory = options.outputDirectory) !== null && _options_outputDirectory !== void 0 ? _options_outputDirectory : KODRDRIV_DEFAULTS.outputDirectory,
562
+ preferencesDirectory: (_options_preferencesDirectory = options.preferencesDirectory) !== null && _options_preferencesDirectory !== void 0 ? _options_preferencesDirectory : KODRDRIV_DEFAULTS.preferencesDirectory,
563
+ // Cardigantime-specific properties (from fileValues or defaults)
564
+ discoveredConfigDirs: (_options_discoveredConfigDirs = options.discoveredConfigDirs) !== null && _options_discoveredConfigDirs !== void 0 ? _options_discoveredConfigDirs : [],
565
+ resolvedConfigDirs: (_options_resolvedConfigDirs = options.resolvedConfigDirs) !== null && _options_resolvedConfigDirs !== void 0 ? _options_resolvedConfigDirs : [],
566
+ // Command-specific options with defaults
567
+ commit: {
568
+ add: (_options_commit_add = (_options_commit = options.commit) === null || _options_commit === void 0 ? void 0 : _options_commit.add) !== null && _options_commit_add !== void 0 ? _options_commit_add : KODRDRIV_DEFAULTS.commit.add,
569
+ cached: (_options_commit_cached = (_options_commit1 = options.commit) === null || _options_commit1 === void 0 ? void 0 : _options_commit1.cached) !== null && _options_commit_cached !== void 0 ? _options_commit_cached : KODRDRIV_DEFAULTS.commit.cached,
570
+ sendit: (_options_commit_sendit = (_options_commit2 = options.commit) === null || _options_commit2 === void 0 ? void 0 : _options_commit2.sendit) !== null && _options_commit_sendit !== void 0 ? _options_commit_sendit : KODRDRIV_DEFAULTS.commit.sendit,
571
+ messageLimit: (_options_commit_messageLimit = (_options_commit3 = options.commit) === null || _options_commit3 === void 0 ? void 0 : _options_commit3.messageLimit) !== null && _options_commit_messageLimit !== void 0 ? _options_commit_messageLimit : KODRDRIV_DEFAULTS.commit.messageLimit,
572
+ context: (_options_commit4 = options.commit) === null || _options_commit4 === void 0 ? void 0 : _options_commit4.context,
573
+ direction: (_options_commit5 = options.commit) === null || _options_commit5 === void 0 ? void 0 : _options_commit5.direction
574
+ },
575
+ audioCommit: {
576
+ maxRecordingTime: (_options_audioCommit_maxRecordingTime = (_options_audioCommit = options.audioCommit) === null || _options_audioCommit === void 0 ? void 0 : _options_audioCommit.maxRecordingTime) !== null && _options_audioCommit_maxRecordingTime !== void 0 ? _options_audioCommit_maxRecordingTime : KODRDRIV_DEFAULTS.audioCommit.maxRecordingTime,
577
+ audioDevice: (_options_audioCommit_audioDevice = (_options_audioCommit1 = options.audioCommit) === null || _options_audioCommit1 === void 0 ? void 0 : _options_audioCommit1.audioDevice) !== null && _options_audioCommit_audioDevice !== void 0 ? _options_audioCommit_audioDevice : KODRDRIV_DEFAULTS.audioCommit.audioDevice,
578
+ file: (_options_audioCommit2 = options.audioCommit) === null || _options_audioCommit2 === void 0 ? void 0 : _options_audioCommit2.file,
579
+ keepTemp: (_options_audioCommit3 = options.audioCommit) === null || _options_audioCommit3 === void 0 ? void 0 : _options_audioCommit3.keepTemp
580
+ },
581
+ release: {
582
+ from: (_options_release_from = (_options_release = options.release) === null || _options_release === void 0 ? void 0 : _options_release.from) !== null && _options_release_from !== void 0 ? _options_release_from : KODRDRIV_DEFAULTS.release.from,
583
+ to: (_options_release_to = (_options_release1 = options.release) === null || _options_release1 === void 0 ? void 0 : _options_release1.to) !== null && _options_release_to !== void 0 ? _options_release_to : KODRDRIV_DEFAULTS.release.to,
584
+ messageLimit: (_options_release_messageLimit = (_options_release2 = options.release) === null || _options_release2 === void 0 ? void 0 : _options_release2.messageLimit) !== null && _options_release_messageLimit !== void 0 ? _options_release_messageLimit : KODRDRIV_DEFAULTS.release.messageLimit,
585
+ context: (_options_release3 = options.release) === null || _options_release3 === void 0 ? void 0 : _options_release3.context
586
+ },
587
+ audioReview: {
588
+ includeCommitHistory: (_options_audioReview_includeCommitHistory = (_options_audioReview = options.audioReview) === null || _options_audioReview === void 0 ? void 0 : _options_audioReview.includeCommitHistory) !== null && _options_audioReview_includeCommitHistory !== void 0 ? _options_audioReview_includeCommitHistory : KODRDRIV_DEFAULTS.audioReview.includeCommitHistory,
589
+ includeRecentDiffs: (_options_audioReview_includeRecentDiffs = (_options_audioReview1 = options.audioReview) === null || _options_audioReview1 === void 0 ? void 0 : _options_audioReview1.includeRecentDiffs) !== null && _options_audioReview_includeRecentDiffs !== void 0 ? _options_audioReview_includeRecentDiffs : KODRDRIV_DEFAULTS.audioReview.includeRecentDiffs,
590
+ includeReleaseNotes: (_options_audioReview_includeReleaseNotes = (_options_audioReview2 = options.audioReview) === null || _options_audioReview2 === void 0 ? void 0 : _options_audioReview2.includeReleaseNotes) !== null && _options_audioReview_includeReleaseNotes !== void 0 ? _options_audioReview_includeReleaseNotes : KODRDRIV_DEFAULTS.audioReview.includeReleaseNotes,
591
+ includeGithubIssues: (_options_audioReview_includeGithubIssues = (_options_audioReview3 = options.audioReview) === null || _options_audioReview3 === void 0 ? void 0 : _options_audioReview3.includeGithubIssues) !== null && _options_audioReview_includeGithubIssues !== void 0 ? _options_audioReview_includeGithubIssues : KODRDRIV_DEFAULTS.audioReview.includeGithubIssues,
592
+ commitHistoryLimit: (_options_audioReview_commitHistoryLimit = (_options_audioReview4 = options.audioReview) === null || _options_audioReview4 === void 0 ? void 0 : _options_audioReview4.commitHistoryLimit) !== null && _options_audioReview_commitHistoryLimit !== void 0 ? _options_audioReview_commitHistoryLimit : KODRDRIV_DEFAULTS.audioReview.commitHistoryLimit,
593
+ diffHistoryLimit: (_options_audioReview_diffHistoryLimit = (_options_audioReview5 = options.audioReview) === null || _options_audioReview5 === void 0 ? void 0 : _options_audioReview5.diffHistoryLimit) !== null && _options_audioReview_diffHistoryLimit !== void 0 ? _options_audioReview_diffHistoryLimit : KODRDRIV_DEFAULTS.audioReview.diffHistoryLimit,
594
+ releaseNotesLimit: (_options_audioReview_releaseNotesLimit = (_options_audioReview6 = options.audioReview) === null || _options_audioReview6 === void 0 ? void 0 : _options_audioReview6.releaseNotesLimit) !== null && _options_audioReview_releaseNotesLimit !== void 0 ? _options_audioReview_releaseNotesLimit : KODRDRIV_DEFAULTS.audioReview.releaseNotesLimit,
595
+ githubIssuesLimit: (_options_audioReview_githubIssuesLimit = (_options_audioReview7 = options.audioReview) === null || _options_audioReview7 === void 0 ? void 0 : _options_audioReview7.githubIssuesLimit) !== null && _options_audioReview_githubIssuesLimit !== void 0 ? _options_audioReview_githubIssuesLimit : KODRDRIV_DEFAULTS.audioReview.githubIssuesLimit,
596
+ context: (_options_audioReview8 = options.audioReview) === null || _options_audioReview8 === void 0 ? void 0 : _options_audioReview8.context,
597
+ sendit: (_options_audioReview_sendit = (_options_audioReview9 = options.audioReview) === null || _options_audioReview9 === void 0 ? void 0 : _options_audioReview9.sendit) !== null && _options_audioReview_sendit !== void 0 ? _options_audioReview_sendit : KODRDRIV_DEFAULTS.audioReview.sendit,
598
+ maxRecordingTime: (_options_audioReview_maxRecordingTime = (_options_audioReview10 = options.audioReview) === null || _options_audioReview10 === void 0 ? void 0 : _options_audioReview10.maxRecordingTime) !== null && _options_audioReview_maxRecordingTime !== void 0 ? _options_audioReview_maxRecordingTime : KODRDRIV_DEFAULTS.audioReview.maxRecordingTime,
599
+ audioDevice: (_options_audioReview_audioDevice = (_options_audioReview11 = options.audioReview) === null || _options_audioReview11 === void 0 ? void 0 : _options_audioReview11.audioDevice) !== null && _options_audioReview_audioDevice !== void 0 ? _options_audioReview_audioDevice : KODRDRIV_DEFAULTS.audioReview.audioDevice,
600
+ file: (_options_audioReview12 = options.audioReview) === null || _options_audioReview12 === void 0 ? void 0 : _options_audioReview12.file,
601
+ keepTemp: (_options_audioReview13 = options.audioReview) === null || _options_audioReview13 === void 0 ? void 0 : _options_audioReview13.keepTemp
602
+ },
603
+ review: {
604
+ includeCommitHistory: (_options_review_includeCommitHistory = (_options_review = options.review) === null || _options_review === void 0 ? void 0 : _options_review.includeCommitHistory) !== null && _options_review_includeCommitHistory !== void 0 ? _options_review_includeCommitHistory : KODRDRIV_DEFAULTS.review.includeCommitHistory,
605
+ includeRecentDiffs: (_options_review_includeRecentDiffs = (_options_review1 = options.review) === null || _options_review1 === void 0 ? void 0 : _options_review1.includeRecentDiffs) !== null && _options_review_includeRecentDiffs !== void 0 ? _options_review_includeRecentDiffs : KODRDRIV_DEFAULTS.review.includeRecentDiffs,
606
+ includeReleaseNotes: (_options_review_includeReleaseNotes = (_options_review2 = options.review) === null || _options_review2 === void 0 ? void 0 : _options_review2.includeReleaseNotes) !== null && _options_review_includeReleaseNotes !== void 0 ? _options_review_includeReleaseNotes : KODRDRIV_DEFAULTS.review.includeReleaseNotes,
607
+ includeGithubIssues: (_options_review_includeGithubIssues = (_options_review3 = options.review) === null || _options_review3 === void 0 ? void 0 : _options_review3.includeGithubIssues) !== null && _options_review_includeGithubIssues !== void 0 ? _options_review_includeGithubIssues : KODRDRIV_DEFAULTS.review.includeGithubIssues,
608
+ commitHistoryLimit: (_options_review_commitHistoryLimit = (_options_review4 = options.review) === null || _options_review4 === void 0 ? void 0 : _options_review4.commitHistoryLimit) !== null && _options_review_commitHistoryLimit !== void 0 ? _options_review_commitHistoryLimit : KODRDRIV_DEFAULTS.review.commitHistoryLimit,
609
+ diffHistoryLimit: (_options_review_diffHistoryLimit = (_options_review5 = options.review) === null || _options_review5 === void 0 ? void 0 : _options_review5.diffHistoryLimit) !== null && _options_review_diffHistoryLimit !== void 0 ? _options_review_diffHistoryLimit : KODRDRIV_DEFAULTS.review.diffHistoryLimit,
610
+ releaseNotesLimit: (_options_review_releaseNotesLimit = (_options_review6 = options.review) === null || _options_review6 === void 0 ? void 0 : _options_review6.releaseNotesLimit) !== null && _options_review_releaseNotesLimit !== void 0 ? _options_review_releaseNotesLimit : KODRDRIV_DEFAULTS.review.releaseNotesLimit,
611
+ githubIssuesLimit: (_options_review_githubIssuesLimit = (_options_review7 = options.review) === null || _options_review7 === void 0 ? void 0 : _options_review7.githubIssuesLimit) !== null && _options_review_githubIssuesLimit !== void 0 ? _options_review_githubIssuesLimit : KODRDRIV_DEFAULTS.review.githubIssuesLimit,
612
+ context: (_options_review8 = options.review) === null || _options_review8 === void 0 ? void 0 : _options_review8.context,
613
+ sendit: (_options_review_sendit = (_options_review9 = options.review) === null || _options_review9 === void 0 ? void 0 : _options_review9.sendit) !== null && _options_review_sendit !== void 0 ? _options_review_sendit : KODRDRIV_DEFAULTS.review.sendit,
614
+ note: (_options_review10 = options.review) === null || _options_review10 === void 0 ? void 0 : _options_review10.note
615
+ },
616
+ publish: {
617
+ mergeMethod: (_options_publish_mergeMethod = (_options_publish = options.publish) === null || _options_publish === void 0 ? void 0 : _options_publish.mergeMethod) !== null && _options_publish_mergeMethod !== void 0 ? _options_publish_mergeMethod : KODRDRIV_DEFAULTS.publish.mergeMethod,
618
+ dependencyUpdatePatterns: (_options_publish1 = options.publish) === null || _options_publish1 === void 0 ? void 0 : _options_publish1.dependencyUpdatePatterns,
619
+ requiredEnvVars: (_options_publish_requiredEnvVars = (_options_publish2 = options.publish) === null || _options_publish2 === void 0 ? void 0 : _options_publish2.requiredEnvVars) !== null && _options_publish_requiredEnvVars !== void 0 ? _options_publish_requiredEnvVars : KODRDRIV_DEFAULTS.publish.requiredEnvVars,
620
+ linkWorkspacePackages: (_options_publish_linkWorkspacePackages = (_options_publish3 = options.publish) === null || _options_publish3 === void 0 ? void 0 : _options_publish3.linkWorkspacePackages) !== null && _options_publish_linkWorkspacePackages !== void 0 ? _options_publish_linkWorkspacePackages : KODRDRIV_DEFAULTS.publish.linkWorkspacePackages,
621
+ unlinkWorkspacePackages: (_options_publish_unlinkWorkspacePackages = (_options_publish4 = options.publish) === null || _options_publish4 === void 0 ? void 0 : _options_publish4.unlinkWorkspacePackages) !== null && _options_publish_unlinkWorkspacePackages !== void 0 ? _options_publish_unlinkWorkspacePackages : KODRDRIV_DEFAULTS.publish.unlinkWorkspacePackages
622
+ },
623
+ link: {
624
+ scopeRoots: (_options_link_scopeRoots = (_options_link = options.link) === null || _options_link === void 0 ? void 0 : _options_link.scopeRoots) !== null && _options_link_scopeRoots !== void 0 ? _options_link_scopeRoots : KODRDRIV_DEFAULTS.link.scopeRoots,
625
+ workspaceFile: (_options_link_workspaceFile = (_options_link1 = options.link) === null || _options_link1 === void 0 ? void 0 : _options_link1.workspaceFile) !== null && _options_link_workspaceFile !== void 0 ? _options_link_workspaceFile : KODRDRIV_DEFAULTS.link.workspaceFile,
626
+ dryRun: (_options_link_dryRun = (_options_link2 = options.link) === null || _options_link2 === void 0 ? void 0 : _options_link2.dryRun) !== null && _options_link_dryRun !== void 0 ? _options_link_dryRun : KODRDRIV_DEFAULTS.link.dryRun
627
+ },
628
+ excludedPatterns: (_options_excludedPatterns = options.excludedPatterns) !== null && _options_excludedPatterns !== void 0 ? _options_excludedPatterns : KODRDRIV_DEFAULTS.excludedPatterns
629
+ };
630
+ // Final validation against the MainConfig shape (optional, cardigantime might handle it)
631
+ // You could potentially use ConfigShape.parse(finalConfig) here if needed
632
+ return finalConfig;
633
+ }
634
+ // Export for testing
635
+ function validateCommand(commandName) {
636
+ if (!ALLOWED_COMMANDS.includes(commandName)) {
637
+ throw new Error(`Invalid command: ${commandName}, allowed commands: ${ALLOWED_COMMANDS.join(', ')}`);
638
+ }
639
+ return commandName;
640
+ }
641
+ // Export for testing
642
+ async function validateContextDirectories(contextDirectories) {
643
+ const logger = getLogger();
644
+ const storage = create({
645
+ log: logger.info
646
+ });
647
+ // Filter out directories that don't exist
648
+ const validDirectories = [];
649
+ for (const dir of contextDirectories){
650
+ try {
651
+ if (await storage.isDirectoryReadable(dir)) {
652
+ validDirectories.push(dir);
653
+ } else {
654
+ logger.warn(`Directory not readable: ${dir}`);
655
+ }
656
+ } catch (error) {
657
+ logger.warn(`Error validating directory ${dir}: ${error.message}`);
658
+ }
659
+ }
660
+ return validDirectories;
661
+ }
662
+
663
+ export { configure, getCliConfig, transformCliArgs, validateAndProcessOptions, validateAndProcessSecureOptions, validateCommand, validateContextDirectories };
664
+ //# sourceMappingURL=arguments.js.map