@@ -32,7 +32,8 @@ export enum CONFIG_KEYS {
32
32
33
33
export enum CONFIG_MODES {
34
34
get = 'get' ,
35
- set = 'set'
35
+ set = 'set' ,
36
+ describe = 'describe'
36
37
}
37
38
38
39
export const MODEL_LIST = {
@@ -622,28 +623,208 @@ export const setConfig = (
622
623
outro ( `${ chalk . green ( '✔' ) } config successfully set` ) ;
623
624
} ;
624
625
626
+ // --- HELP MESSAGE GENERATION ---
627
+ function getConfigKeyDetails ( key ) {
628
+ switch ( key ) {
629
+ case CONFIG_KEYS . OCO_MODEL :
630
+ return {
631
+ description : 'The AI model to use for generating commit messages' ,
632
+ values : MODEL_LIST
633
+ } ;
634
+ case CONFIG_KEYS . OCO_AI_PROVIDER :
635
+ return {
636
+ description : 'The AI provider to use' ,
637
+ values : Object . values ( OCO_AI_PROVIDER_ENUM )
638
+ } ;
639
+ case CONFIG_KEYS . OCO_PROMPT_MODULE :
640
+ return {
641
+ description : 'The prompt module to use for commit message generation' ,
642
+ values : Object . values ( OCO_PROMPT_MODULE_ENUM )
643
+ } ;
644
+ case CONFIG_KEYS . OCO_LANGUAGE :
645
+ return {
646
+ description : 'The locale to use for commit messages' ,
647
+ values : Object . keys ( i18n )
648
+ } ;
649
+ case CONFIG_KEYS . OCO_TEST_MOCK_TYPE :
650
+ return {
651
+ description : 'The type of test mock to use' ,
652
+ values : [ 'commit-message' , 'prompt-module-commitlint-config' ]
653
+ } ;
654
+ case CONFIG_KEYS . OCO_ONE_LINE_COMMIT :
655
+ return {
656
+ description : 'One line commit message' ,
657
+ values : [ 'true' , 'false' ]
658
+ } ;
659
+ case CONFIG_KEYS . OCO_DESCRIPTION :
660
+ return {
661
+ description : 'Postface a message with ~3 sentences description of the changes' ,
662
+ values : [ 'true' , 'false' ]
663
+ } ;
664
+ case CONFIG_KEYS . OCO_EMOJI :
665
+ return {
666
+ description : 'Preface a message with GitMoji' ,
667
+ values : [ 'true' , 'false' ]
668
+ } ;
669
+ case CONFIG_KEYS . OCO_WHY :
670
+ return {
671
+ description : 'Output a short description of why the changes were done after the commit message (default: false)' ,
672
+ values : [ 'true' , 'false' ]
673
+ }
674
+ case CONFIG_KEYS . OCO_OMIT_SCOPE :
675
+ return {
676
+ description : 'Do not include a scope in the commit message' ,
677
+ values : [ 'true' , 'false' ]
678
+ } ;
679
+ case CONFIG_KEYS . OCO_GITPUSH :
680
+ return {
681
+ description : 'Push to git after commit (deprecated). If false, oco will exit after committing' ,
682
+ values : [ 'true' , 'false' ]
683
+ } ;
684
+ case CONFIG_KEYS . OCO_TOKENS_MAX_INPUT :
685
+ return {
686
+ description : 'Max model token limit' ,
687
+ values : [ 'Any positive integer' ]
688
+ } ;
689
+ case CONFIG_KEYS . OCO_TOKENS_MAX_OUTPUT :
690
+ return {
691
+ description : 'Max response tokens' ,
692
+ values : [ 'Any positive integer' ]
693
+ } ;
694
+ case CONFIG_KEYS . OCO_API_KEY :
695
+ return {
696
+ description : 'API key for the selected provider' ,
697
+ values : [ 'String (required for most providers)' ]
698
+ } ;
699
+ case CONFIG_KEYS . OCO_API_URL :
700
+ return {
701
+ description : 'Custom API URL - may be used to set proxy path to OpenAI API' ,
702
+ values : [ "URL string (must start with 'http://' or 'https://')" ]
703
+ } ;
704
+ case CONFIG_KEYS . OCO_MESSAGE_TEMPLATE_PLACEHOLDER :
705
+ return {
706
+ description : 'Message template placeholder' ,
707
+ values : [ "String (must start with $)" ]
708
+ } ;
709
+ default :
710
+ return {
711
+ description : 'String value' ,
712
+ values : [ 'Any string' ]
713
+ } ;
714
+ }
715
+ }
716
+
717
+ function printConfigKeyHelp ( param ) {
718
+ if ( ! Object . values ( CONFIG_KEYS ) . includes ( param ) ) {
719
+ console . log ( chalk . red ( `Unknown config parameter: ${ param } ` ) ) ;
720
+ return ;
721
+ }
722
+
723
+ const details = getConfigKeyDetails ( param as CONFIG_KEYS ) ;
724
+
725
+ let desc = details . description ;
726
+ let defaultValue = undefined ;
727
+ if ( param in DEFAULT_CONFIG ) {
728
+ defaultValue = DEFAULT_CONFIG [ param ] ;
729
+ }
730
+
731
+
732
+ console . log ( chalk . bold ( `\n${ param } :` ) ) ;
733
+ console . log ( chalk . gray ( ` Description: ${ desc } ` ) ) ;
734
+ if ( defaultValue !== undefined ) {
735
+ // Print booleans and numbers as-is, strings without quotes
736
+ if ( typeof defaultValue === 'string' ) {
737
+ console . log ( chalk . gray ( ` Default: ${ defaultValue } ` ) ) ;
738
+ } else {
739
+ console . log ( chalk . gray ( ` Default: ${ defaultValue } ` ) ) ;
740
+ }
741
+ }
742
+
743
+ if ( Array . isArray ( details . values ) ) {
744
+ console . log ( chalk . gray ( ' Accepted values:' ) ) ;
745
+ details . values . forEach ( value => {
746
+ console . log ( chalk . gray ( ` - ${ value } ` ) ) ;
747
+ } ) ;
748
+ } else {
749
+ console . log ( chalk . gray ( ' Accepted values by provider:' ) ) ;
750
+ Object . entries ( details . values ) . forEach ( ( [ provider , values ] ) => {
751
+ console . log ( chalk . gray ( ` ${ provider } :` ) ) ;
752
+ ( values as string [ ] ) . forEach ( value => {
753
+ console . log ( chalk . gray ( ` - ${ value } ` ) ) ;
754
+ } ) ;
755
+ } ) ;
756
+ }
757
+ }
758
+
759
+ function printAllConfigHelp ( ) {
760
+ console . log ( chalk . bold ( 'Available config parameters:' ) ) ;
761
+ for ( const key of Object . values ( CONFIG_KEYS ) . sort ( ) ) {
762
+ const details = getConfigKeyDetails ( key ) ;
763
+ // Try to get the default value from DEFAULT_CONFIG
764
+ let defaultValue = undefined ;
765
+ if ( key in DEFAULT_CONFIG ) {
766
+ defaultValue = DEFAULT_CONFIG [ key ] ;
767
+ }
768
+
769
+ console . log ( chalk . bold ( `\n${ key } :` ) ) ;
770
+ console . log ( chalk . gray ( ` Description: ${ details . description } ` ) ) ;
771
+ if ( defaultValue !== undefined ) {
772
+ if ( typeof defaultValue === 'string' ) {
773
+ console . log ( chalk . gray ( ` Default: ${ defaultValue } ` ) ) ;
774
+ } else {
775
+ console . log ( chalk . gray ( ` Default: ${ defaultValue } ` ) ) ;
776
+ }
777
+ }
778
+ }
779
+ console . log ( chalk . yellow ( '\nUse "oco config describe [PARAMETER]" to see accepted values and more details for a specific config parameter.' ) ) ;
780
+ }
781
+
625
782
export const configCommand = command (
626
783
{
627
784
name : COMMANDS . config ,
628
- parameters : [ '<mode>' , '<key=values...>' ]
785
+ parameters : [ '<mode>' , '[key=values...]' ] ,
786
+ help : {
787
+ description : 'Configure opencommit settings' ,
788
+ examples : [
789
+ 'Describe all config parameters: oco config describe' ,
790
+ 'Describe a specific parameter: oco config describe OCO_MODEL' ,
791
+ 'Get a config value: oco config get OCO_MODEL' ,
792
+ 'Set a config value: oco config set OCO_MODEL=gpt-4'
793
+ ]
794
+ }
629
795
} ,
630
796
async ( argv ) => {
631
797
try {
632
798
const { mode, keyValues } = argv . _ ;
633
799
intro ( `COMMAND: config ${ mode } ${ keyValues } ` ) ;
634
800
635
- if ( mode === CONFIG_MODES . get ) {
801
+ if ( mode === CONFIG_MODES . describe ) {
802
+ if ( ! keyValues || keyValues . length === 0 ) {
803
+ printAllConfigHelp ( ) ;
804
+ } else {
805
+ for ( const key of keyValues ) {
806
+ printConfigKeyHelp ( key ) ;
807
+ }
808
+ }
809
+ process . exit ( 0 ) ;
810
+ } else if ( mode === CONFIG_MODES . get ) {
811
+ if ( ! keyValues || keyValues . length === 0 ) {
812
+ throw new Error ( 'No config keys specified for get mode' ) ;
813
+ }
636
814
const config = getConfig ( ) || { } ;
637
815
for ( const key of keyValues ) {
638
816
outro ( `${ key } =${ config [ key as keyof typeof config ] } ` ) ;
639
817
}
640
818
} else if ( mode === CONFIG_MODES . set ) {
819
+ if ( ! keyValues || keyValues . length === 0 ) {
820
+ throw new Error ( 'No config keys specified for set mode' ) ;
821
+ }
641
822
await setConfig (
642
823
keyValues . map ( ( keyValue ) => keyValue . split ( '=' ) as [ string , string ] )
643
824
) ;
644
825
} else {
645
826
throw new Error (
646
- `Unsupported mode: ${ mode } . Valid modes are: "set" and "get "`
827
+ `Unsupported mode: ${ mode } . Valid modes are: "set", "get", and "describe "`
647
828
) ;
648
829
}
649
830
} catch ( error ) {
0 commit comments