git-coco 0.5.0 β†’ 0.6.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.
Files changed (56) hide show
  1. package/dist/index.d.ts +263 -2
  2. package/dist/index.esm.mjs +427 -52
  3. package/dist/index.js +428 -51
  4. package/package.json +12 -5
  5. package/dist/commands/changelog/handler.d.ts +0 -3
  6. package/dist/commands/changelog/index.d.ts +0 -10
  7. package/dist/commands/changelog/options.d.ts +0 -16
  8. package/dist/commands/commit/handler.d.ts +0 -3
  9. package/dist/commands/commit/index.d.ts +0 -10
  10. package/dist/commands/commit/options.d.ts +0 -15
  11. package/dist/commands/types.d.ts +0 -14
  12. package/dist/index.esm.mjs.map +0 -1
  13. package/dist/lib/config/loadConfig.d.ts +0 -25
  14. package/dist/lib/config/services/env.d.ts +0 -8
  15. package/dist/lib/config/services/git.d.ts +0 -8
  16. package/dist/lib/config/services/ignore.d.ts +0 -15
  17. package/dist/lib/config/services/project.d.ts +0 -8
  18. package/dist/lib/config/services/xdg.d.ts +0 -8
  19. package/dist/lib/config/types.d.ts +0 -83
  20. package/dist/lib/langchain/chains/summarize.d.ts +0 -11
  21. package/dist/lib/langchain/executeChain.d.ts +0 -6
  22. package/dist/lib/langchain/prompts/changelog.d.ts +0 -3
  23. package/dist/lib/langchain/prompts/commitDefault.d.ts +0 -3
  24. package/dist/lib/langchain/prompts/summarize.d.ts +0 -3
  25. package/dist/lib/langchain/utils.d.ts +0 -48
  26. package/dist/lib/parsers/default/index.d.ts +0 -2
  27. package/dist/lib/parsers/default/utils/collectDiffs.d.ts +0 -8
  28. package/dist/lib/parsers/default/utils/createDiffTree.d.ts +0 -13
  29. package/dist/lib/parsers/default/utils/summarizeDiffs.d.ts +0 -26
  30. package/dist/lib/parsers/noResult.d.ts +0 -8
  31. package/dist/lib/simple-git/createCommit.d.ts +0 -2
  32. package/dist/lib/simple-git/getChanges.d.ts +0 -15
  33. package/dist/lib/simple-git/getChangesByCommit.d.ts +0 -13
  34. package/dist/lib/simple-git/getCommitLogCurrentBranch.d.ts +0 -9
  35. package/dist/lib/simple-git/getCommitLogRange.d.ts +0 -7
  36. package/dist/lib/simple-git/getCurrentBranchName.d.ts +0 -5
  37. package/dist/lib/simple-git/getDiff.d.ts +0 -7
  38. package/dist/lib/simple-git/getDiffFromCommmit.d.ts +0 -10
  39. package/dist/lib/simple-git/getRepo.d.ts +0 -2
  40. package/dist/lib/simple-git/getStatus.d.ts +0 -3
  41. package/dist/lib/simple-git/getSummaryText.d.ts +0 -3
  42. package/dist/lib/simple-git/helpers.d.ts +0 -6
  43. package/dist/lib/types.d.ts +0 -47
  44. package/dist/lib/ui/editPrompt.d.ts +0 -2
  45. package/dist/lib/ui/editResult.d.ts +0 -2
  46. package/dist/lib/ui/generateAndReviewLoop.d.ts +0 -16
  47. package/dist/lib/ui/getUserReviewDecision.d.ts +0 -2
  48. package/dist/lib/ui/handleResult.d.ts +0 -5
  49. package/dist/lib/ui/helpers.d.ts +0 -3
  50. package/dist/lib/ui/logResult.d.ts +0 -1
  51. package/dist/lib/ui/logSuccess.d.ts +0 -1
  52. package/dist/lib/utils/getPathFromFilePath.d.ts +0 -6
  53. package/dist/lib/utils/getTokenizer.d.ts +0 -9
  54. package/dist/lib/utils/logger.d.ts +0 -23
  55. package/dist/lib/utils/removeUndefined.d.ts +0 -9
  56. package/dist/stats.html +0 -5305
@@ -17,9 +17,11 @@ import * as path from 'path';
17
17
  import path__default from 'path';
18
18
  import { minimatch } from 'minimatch';
19
19
  import * as fs from 'fs';
20
+ import fs__default from 'fs';
21
+ import { confirm, editor, select, password, input } from '@inquirer/prompts';
20
22
  import * as os from 'os';
23
+ import os__default from 'os';
21
24
  import * as ini from 'ini';
22
- import { editor, select } from '@inquirer/prompts';
23
25
  import { simpleGit } from 'simple-git';
24
26
 
25
27
  /**
@@ -583,6 +585,82 @@ function removeUndefined(obj) {
583
585
  return Object.fromEntries(Object.entries(obj).filter(([, value]) => value !== undefined));
584
586
  }
585
587
 
588
+ /**
589
+ * Default Config
590
+ *
591
+ * @type {Config}
592
+ */
593
+ const DEFAULT_CONFIG = {
594
+ model: 'openai/gpt-4',
595
+ verbose: false,
596
+ tokenLimit: 1024,
597
+ summarizePrompt: SUMMARIZE_PROMPT.template,
598
+ temperature: 0.4,
599
+ mode: 'stdout',
600
+ ignoredFiles: ['package-lock.json'],
601
+ ignoredExtensions: ['.map', '.lock'],
602
+ defaultBranch: 'main',
603
+ };
604
+ /**
605
+ * Config keys
606
+ *
607
+ * @type {string[]}
608
+ */
609
+ const CONFIG_KEYS = Object.keys({
610
+ ...DEFAULT_CONFIG,
611
+ huggingFaceHubApiKey: '',
612
+ openAIApiKey: '',
613
+ prompt: '',
614
+ });
615
+
616
+ async function updateFileSection(filePath, startComment, endComment, getNewContent, confirmUpdate = true) {
617
+ const lines = fs__default.existsSync(filePath) ? fs__default.readFileSync(filePath, 'utf-8').split(/\r?\n/) : [];
618
+ const newLines = [];
619
+ let foundSection = false;
620
+ for (let i = 0; i < lines.length; i++) {
621
+ if (lines[i].trim() === startComment) {
622
+ foundSection = true;
623
+ if (confirmUpdate) {
624
+ const confirmOverwrite = await confirm({
625
+ message: `A section already exists in ${filePath}, do you want to override it?`,
626
+ default: false,
627
+ });
628
+ if (!confirmOverwrite) {
629
+ // keep all lines until the end comment
630
+ while (i < lines.length && lines[i].trim() !== endComment) {
631
+ newLines.push(lines[i]);
632
+ i++;
633
+ }
634
+ newLines.push(endComment);
635
+ continue;
636
+ }
637
+ }
638
+ newLines.push(startComment);
639
+ // Insert the new content
640
+ const newContent = await getNewContent();
641
+ newLines.push(newContent);
642
+ // Skip the existing content of the section
643
+ while (i < lines.length && lines[i].trim() !== endComment) {
644
+ i++;
645
+ }
646
+ newLines.push(endComment);
647
+ continue;
648
+ }
649
+ if (!foundSection || lines[i].trim() !== endComment) {
650
+ newLines.push(lines[i]);
651
+ }
652
+ }
653
+ // If section wasn't found, append it at the end
654
+ if (!foundSection) {
655
+ newLines.push('\n' + startComment);
656
+ const newContent = await getNewContent();
657
+ newLines.push(newContent);
658
+ newLines.push(endComment);
659
+ }
660
+ // Write the updated contents back to the file
661
+ fs__default.writeFileSync(filePath, newLines.join('\n'));
662
+ }
663
+
586
664
  /**
587
665
  * Load environment variables
588
666
  *
@@ -590,27 +668,65 @@ function removeUndefined(obj) {
590
668
  * @returns {Config} Updated config
591
669
  **/
592
670
  function loadEnvConfig(config) {
593
- const envConfig = {
594
- model: process.env.COCO_MODEL || undefined,
595
- openAIApiKey: process.env.OPENAI_API_KEY || undefined,
596
- huggingFaceHubApiKey: process.env.HUGGINGFACE_HUB_API_KEY || undefined,
597
- tokenLimit: process.env.COCO_TOKEN_LIMIT
598
- ? parseInt(process.env.COCO_TOKEN_LIMIT)
599
- : undefined,
600
- prompt: process.env.COCO_PROMPT,
601
- mode: process.env.COCO_MODE,
602
- summarizePrompt: process.env.COCO_SUMMARIZE_PROMPT,
603
- ignoredFiles: process.env.COCO_IGNORED_FILES
604
- ? process.env.COCO_IGNORED_FILES.split(',')
605
- : undefined,
606
- ignoredExtensions: process.env.COCO_IGNORED_EXTENSIONS
607
- ? process.env.COCO_IGNORED_EXTENSIONS.split(',')
608
- : undefined,
609
- defaultBranch: process.env.COCO_DEFAULT_BRANCH || undefined,
610
- };
611
- config = { ...config, ...removeUndefined(envConfig) };
612
- return config;
671
+ const envConfig = {};
672
+ CONFIG_KEYS.forEach((key) => {
673
+ const envVarName = toEnvVarName(key);
674
+ const envValue = parseEnvValue(key, process.env[envVarName]);
675
+ if (envValue === undefined)
676
+ return;
677
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
678
+ // @ts-ignore
679
+ envConfig[key] = envValue;
680
+ });
681
+ return { ...config, ...removeUndefined(envConfig) };
682
+ }
683
+ function parseEnvValue(key, value) {
684
+ if (value === undefined) {
685
+ return undefined;
686
+ }
687
+ else if (key === 'tokenLimit' && typeof value === 'string') {
688
+ return parseInt(value);
689
+ }
690
+ else if ((key === 'ignoredFiles' || key === 'ignoredExtensions') &&
691
+ typeof value === 'string' &&
692
+ value.includes(',')) {
693
+ return value.split(',');
694
+ }
695
+ return value;
696
+ }
697
+ function toEnvVarName(key) {
698
+ switch (key) {
699
+ case 'openAIApiKey':
700
+ return 'OPENAI_API_KEY';
701
+ case 'huggingFaceHubApiKey':
702
+ return 'HUGGINGFACE_HUB_API_KEY';
703
+ default:
704
+ return 'COCO_' + key.replace(/([A-Z])/g, '_$1').toUpperCase();
705
+ }
613
706
  }
707
+ function formatEnvValue(value) {
708
+ if (typeof value === 'number') {
709
+ return `${value}`;
710
+ }
711
+ else if (Array.isArray(value)) {
712
+ return `${value.join(',')}`;
713
+ }
714
+ else if (typeof value === 'string') {
715
+ // Escape newlines and tabs in strings
716
+ return `${value.replace(/\n/g, '\\n').replace(/\t/g, '\\t')}`;
717
+ }
718
+ return `${value}`;
719
+ }
720
+ const appendToEnvFile = async (filePath, config) => {
721
+ const startComment = '# -- Start coco config --';
722
+ const endComment = '# -- End coco config --';
723
+ const getNewContent = async () => {
724
+ return Object.entries(config)
725
+ .map(([key, value]) => `${toEnvVarName(key)}=${formatEnvValue(value)}`)
726
+ .join('\n');
727
+ };
728
+ await updateFileSection(filePath, startComment, endComment, getNewContent);
729
+ };
614
730
 
615
731
  /**
616
732
  * Load git profile config (from ~/.gitconfig)
@@ -640,6 +756,38 @@ function loadGitConfig(config) {
640
756
  }
641
757
  return config;
642
758
  }
759
+ /**
760
+ * Appends the provided configuration to a git config file.
761
+ *
762
+ * @param filePath - The path to the .gitconfig
763
+ * @param config - The configuration object to append.
764
+ */
765
+ const appendToGitConfig = async (filePath, config) => {
766
+ if (!fs.existsSync(filePath)) {
767
+ throw new Error(`File ${filePath} does not exist.`);
768
+ }
769
+ const startComment = '# -- Start coco config --';
770
+ const endComment = '# -- End coco config --';
771
+ const header = '[coco]';
772
+ // Function to generate new content for the coco section
773
+ const getNewContent = async () => {
774
+ const contentLines = [header];
775
+ for (const key in config) {
776
+ // check if string has new lines, if so, wrap in quotes
777
+ if (typeof config[key] === 'string') {
778
+ const value = config[key];
779
+ if (value.includes('\n')) {
780
+ contentLines.push(`\t${key} = ${JSON.stringify(value)}`);
781
+ continue;
782
+ }
783
+ }
784
+ contentLines.push(`\t${key} = ${config[key]}`);
785
+ }
786
+ return contentLines.join('\n');
787
+ };
788
+ // Use the updateFileSection utility
789
+ await updateFileSection(filePath, startComment, endComment, getNewContent);
790
+ };
643
791
 
644
792
  /**
645
793
  * Load .gitignore in project root
@@ -689,6 +837,12 @@ function loadProjectConfig(config) {
689
837
  }
690
838
  return config;
691
839
  }
840
+ const appendToProjectConfig = (filePath, config) => {
841
+ fs.writeFileSync(filePath, JSON.stringify({
842
+ $schema: 'https://git-co.co/schema.json',
843
+ ...config,
844
+ }, null, 2));
845
+ };
692
846
 
693
847
  /**
694
848
  * Load XDG config
@@ -706,22 +860,6 @@ function loadXDGConfig(config) {
706
860
  return config;
707
861
  }
708
862
 
709
- /**
710
- * Default Config
711
- *
712
- * @type {Config}
713
- */
714
- const DEFAULT_CONFIG = {
715
- model: 'openai/gpt-4',
716
- verbose: false,
717
- tokenLimit: 1024,
718
- summarizePrompt: SUMMARIZE_PROMPT.template,
719
- temperature: 0.4,
720
- mode: 'stdout',
721
- ignoredFiles: ['package-lock.json'],
722
- ignoredExtensions: ['.map', '.lock'],
723
- defaultBranch: 'main',
724
- };
725
863
  /**
726
864
  * Load application config
727
865
  *
@@ -841,8 +979,8 @@ const isInteractive = (argv) => {
841
979
  };
842
980
  const SEPERATOR = chalk.blue('----------------');
843
981
 
844
- function logResult(result) {
845
- console.log(`\n${chalk.bgBlue(chalk.bold('Proposed Commit:'))}\n${SEPERATOR}\n${result}\n${SEPERATOR}\n`);
982
+ function logResult(label, result) {
983
+ console.log(`\n${chalk.bgBlue(chalk.bold(`Proposed ${label}:`))}\n${SEPERATOR}\n${result}\n${SEPERATOR}\n`);
846
984
  }
847
985
 
848
986
  async function editResult(result, options) {
@@ -943,7 +1081,7 @@ async function generateAndReviewLoop({ label, factory, parser, noResult, agent,
943
1081
  })
944
1082
  .stopTimer();
945
1083
  if (options?.interactive) {
946
- logResult(result);
1084
+ logResult(label, result);
947
1085
  const reviewAnswer = await getUserReviewDecision();
948
1086
  if (reviewAnswer === 'cancel') {
949
1087
  process.exit(0);
@@ -1033,7 +1171,7 @@ const getRepo = () => {
1033
1171
  return git;
1034
1172
  };
1035
1173
 
1036
- async function handler$1(argv) {
1174
+ async function handler$2(argv) {
1037
1175
  const tokenizer = getTokenizer();
1038
1176
  const git = getRepo();
1039
1177
  const options = loadConfig(argv);
@@ -1095,7 +1233,7 @@ async function handler$1(argv) {
1095
1233
  /**
1096
1234
  * Command line options via yargs
1097
1235
  */
1098
- const options$1 = {
1236
+ const options$2 = {
1099
1237
  model: { type: 'string', description: 'LLM/Model-Name' },
1100
1238
  openAIApiKey: {
1101
1239
  type: 'string',
@@ -1141,16 +1279,16 @@ const options$1 = {
1141
1279
  description: 'Ignored extensions',
1142
1280
  },
1143
1281
  };
1144
- const builder$1 = (yargs) => {
1145
- return yargs.options(options$1);
1282
+ const builder$2 = (yargs) => {
1283
+ return yargs.options(options$2);
1146
1284
  };
1147
1285
 
1148
1286
  var commit = {
1149
1287
  command: 'commit',
1150
1288
  desc: 'Generate commit message',
1151
- builder: builder$1,
1152
- handler: handler$1,
1153
- options: options$1,
1289
+ builder: builder$2,
1290
+ handler: handler$2,
1291
+ options: options$2,
1154
1292
  };
1155
1293
 
1156
1294
  const template = `Write informative git changelog, in the imperative, based on a series of individual messages.
@@ -1226,7 +1364,7 @@ async function getCommitLogCurrentBranch({ git, logger, comparisonBranch = 'main
1226
1364
  return [];
1227
1365
  }
1228
1366
 
1229
- async function handler(argv) {
1367
+ async function handler$1(argv) {
1230
1368
  const options = loadConfig(argv);
1231
1369
  const logger = new Logger(options);
1232
1370
  const git = getRepo();
@@ -1297,7 +1435,7 @@ async function handler(argv) {
1297
1435
  /**
1298
1436
  * Command line options via yargs
1299
1437
  */
1300
- const options = {
1438
+ const options$1 = {
1301
1439
  range: {
1302
1440
  type: 'string',
1303
1441
  alias: 'r',
@@ -1343,18 +1481,249 @@ const options = {
1343
1481
  description: 'Ignored extensions',
1344
1482
  },
1345
1483
  };
1346
- const builder = (yargs) => {
1347
- return yargs.options(options);
1484
+ const builder$1 = (yargs) => {
1485
+ return yargs.options(options$1);
1348
1486
  };
1349
1487
 
1350
1488
  var changelog = {
1351
1489
  command: 'changelog',
1352
1490
  desc: 'Generate a changelog from a commit range',
1491
+ builder: builder$1,
1492
+ handler: handler$1,
1493
+ options: options$1,
1494
+ };
1495
+
1496
+ const handleProjectLevelConfig = async () => {
1497
+ const projectConfiguration = await select({
1498
+ message: 'select type project level configuration:',
1499
+ choices: [
1500
+ {
1501
+ name: '.coco.config.json',
1502
+ value: '.coco.config.json',
1503
+ },
1504
+ {
1505
+ name: '.env',
1506
+ value: '.env',
1507
+ },
1508
+ ],
1509
+ });
1510
+ let configFile = '.coco.config.json';
1511
+ if (projectConfiguration === '.env') {
1512
+ configFile = '.env';
1513
+ if (!fs__default.existsSync('.env')) {
1514
+ fs__default.writeFileSync('.env', '');
1515
+ }
1516
+ }
1517
+ return configFile;
1518
+ };
1519
+ const handleSystemLevelConfig = () => {
1520
+ return path__default.join(os__default.homedir(), '.gitconfig');
1521
+ };
1522
+ async function handler(argv) {
1523
+ const options = loadConfig(argv);
1524
+ const logger = new Logger(options);
1525
+ const level = await select({
1526
+ message: 'configure coco at the system or project level:',
1527
+ choices: [
1528
+ {
1529
+ name: 'system',
1530
+ value: 'system',
1531
+ description: 'add coco config to your global git config',
1532
+ },
1533
+ {
1534
+ name: 'project',
1535
+ value: 'project',
1536
+ description: 'add coco config to existing git project',
1537
+ },
1538
+ ],
1539
+ });
1540
+ let configFilePath = '';
1541
+ switch (level) {
1542
+ case 'system':
1543
+ configFilePath = await handleSystemLevelConfig();
1544
+ break;
1545
+ case 'project':
1546
+ configFilePath = await handleProjectLevelConfig();
1547
+ break;
1548
+ }
1549
+ // interactive v.s stdout mode
1550
+ const mode = (await select({
1551
+ message: 'select mode:',
1552
+ choices: [
1553
+ {
1554
+ name: 'interactive',
1555
+ value: 'interactive',
1556
+ description: 'interactive prompt for creating, reviewing, and committing',
1557
+ },
1558
+ {
1559
+ name: 'stdout',
1560
+ value: 'stdout',
1561
+ description: 'print results to stdout',
1562
+ },
1563
+ ],
1564
+ }));
1565
+ const apiKey = await password({
1566
+ message: `enter your OpenAI API key:`,
1567
+ validate(input) {
1568
+ return input.length > 0 ? true : 'API key cannot be empty';
1569
+ },
1570
+ });
1571
+ const tokenLimit = await input({
1572
+ message: 'maximum number of tokens for the commit message:',
1573
+ default: '500',
1574
+ });
1575
+ const defaultBranch = await input({
1576
+ message: 'default branch for the repository:',
1577
+ default: 'main',
1578
+ });
1579
+ const advOptions = await confirm({
1580
+ message: 'would you like to configure advanced options?',
1581
+ default: false,
1582
+ });
1583
+ const config = {
1584
+ openAIApiKey: 'β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’',
1585
+ tokenLimit: parseInt(tokenLimit),
1586
+ defaultBranch,
1587
+ mode,
1588
+ };
1589
+ /**
1590
+ * Prompt for advanced options
1591
+ *
1592
+ * e.g.
1593
+ * - temperature
1594
+ * - verbose logging
1595
+ * - ignored files
1596
+ * - ignored extensions
1597
+ * - commit message prompt
1598
+ */
1599
+ if (advOptions) {
1600
+ const temperature = await input({
1601
+ message: 'temperature for the model:',
1602
+ default: '0.4',
1603
+ });
1604
+ config.temperature = parseFloat(temperature);
1605
+ config.verbose = await confirm({
1606
+ message: 'enable verbose logging:',
1607
+ default: false,
1608
+ });
1609
+ const promptForIgnores = await confirm({
1610
+ message: 'would you like to configure ignored files and extensions?',
1611
+ default: false,
1612
+ });
1613
+ if (promptForIgnores) {
1614
+ const ignoredFiles = await input({
1615
+ message: 'paths of files to be excluded when generating commit messages (comma-separated):',
1616
+ default: 'package-lock.json',
1617
+ });
1618
+ const ignoredExtensions = await input({
1619
+ message: 'file extensions to be excluded when generating commit messages (comma-separated):',
1620
+ default: '.map, .lock',
1621
+ });
1622
+ config.ignoredFiles =
1623
+ (ignoredFiles && ignoredFiles.split(',').map((file) => file.trim())) || [];
1624
+ config.ignoredExtensions =
1625
+ (ignoredExtensions && ignoredExtensions.split(',').map((ext) => ext.trim())) || [];
1626
+ }
1627
+ const promptForCommitPrompt = await confirm({
1628
+ message: 'would you like to configure the commit message prompt?',
1629
+ default: false,
1630
+ });
1631
+ if (promptForCommitPrompt) {
1632
+ const commitPrompt = await editor({
1633
+ message: 'modify default commit message prompt:',
1634
+ default: COMMIT_PROMPT.template,
1635
+ });
1636
+ config.prompt = commitPrompt;
1637
+ }
1638
+ }
1639
+ logResult('Config', JSON.stringify(config, null, 2));
1640
+ // add to config after logging, so that the API key is not logged
1641
+ config.openAIApiKey = apiKey;
1642
+ const isApproved = await confirm({
1643
+ message: 'look good? (hiding API key for security)',
1644
+ });
1645
+ if (isApproved) {
1646
+ if (configFilePath.endsWith('.gitconfig')) {
1647
+ await appendToGitConfig(configFilePath, config);
1648
+ }
1649
+ else if (configFilePath === '.env') {
1650
+ await appendToEnvFile(configFilePath, config);
1651
+ }
1652
+ else if (configFilePath === '.coco.config.json') {
1653
+ await appendToProjectConfig(configFilePath, config);
1654
+ }
1655
+ logger.log(`init successful! πŸ¦ΎπŸ€–πŸŽ‰`, { color: 'green' });
1656
+ }
1657
+ else {
1658
+ logger.log('init cancelled.', { color: 'yellow' });
1659
+ }
1660
+ }
1661
+
1662
+ /**
1663
+ * Command line options via yargs
1664
+ */
1665
+ const options = {
1666
+ model: { type: 'string', description: 'LLM/Model-Name' },
1667
+ openAIApiKey: {
1668
+ type: 'string',
1669
+ description: 'OpenAI API Key',
1670
+ conflicts: 'huggingFaceHubApiKey',
1671
+ },
1672
+ huggingFaceHubApiKey: {
1673
+ type: 'string',
1674
+ description: 'HuggingFace Hub API Key',
1675
+ conflicts: 'openAIApiKey',
1676
+ },
1677
+ tokenLimit: { type: 'number', description: 'Token limit' },
1678
+ prompt: {
1679
+ type: 'string',
1680
+ alias: 'p',
1681
+ description: 'Commit message prompt',
1682
+ },
1683
+ i: {
1684
+ type: 'boolean',
1685
+ alias: 'interactive',
1686
+ description: 'Toggle interactive mode',
1687
+ },
1688
+ s: {
1689
+ type: 'boolean',
1690
+ description: 'Automatically commit staged changes with generated commit message',
1691
+ default: false,
1692
+ },
1693
+ e: {
1694
+ type: 'boolean',
1695
+ alias: 'edit',
1696
+ description: 'Open commit message in editor before proceeding',
1697
+ },
1698
+ summarizePrompt: {
1699
+ type: 'string',
1700
+ description: 'Large file summary prompt',
1701
+ },
1702
+ ignoredFiles: {
1703
+ type: 'array',
1704
+ description: 'Ignored files',
1705
+ },
1706
+ ignoredExtensions: {
1707
+ type: 'array',
1708
+ description: 'Ignored extensions',
1709
+ },
1710
+ };
1711
+ const builder = (yargs) => {
1712
+ return yargs.options(options);
1713
+ };
1714
+
1715
+ var init = {
1716
+ command: 'init',
1717
+ desc: 'Setup coco for a new project or system',
1353
1718
  builder,
1354
1719
  handler,
1355
1720
  options,
1356
1721
  };
1357
1722
 
1723
+ var types = /*#__PURE__*/Object.freeze({
1724
+ __proto__: null
1725
+ });
1726
+
1358
1727
  yargs
1359
1728
  .scriptName('coco')
1360
1729
  .usage('$0 <cmd> [args]')
@@ -1368,6 +1737,12 @@ commit.builder, commit.handler)
1368
1737
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
1369
1738
  // @ts-ignore
1370
1739
  changelog.builder, changelog.handler)
1740
+ .command(init.command, init.desc,
1741
+ // TODO: fix type on builder
1742
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
1743
+ // @ts-ignore
1744
+ init.builder, init.handler)
1371
1745
  .demandCommand()
1372
1746
  .help().argv;
1373
- //# sourceMappingURL=index.esm.mjs.map
1747
+
1748
+ export { changelog, commit, init, types };