11/**
2- * git commit flow with auto-generated commit message
2+ * Script to automate the git commit process with AI-generated commit messages.
3+ * It checks for staged changes, generates a commit message, and prompts the user to review or edit the message before committing.
34 */
5+
46script ( {
57 title : "git commit message" ,
68 description : "Generate a commit message for all staged changes" ,
@@ -9,40 +11,104 @@ script({
911// Check for staged changes and stage all changes if none are staged
1012const diff = await git . diff ( {
1113 staged : true ,
12- excludedPaths : "**/genaiscript.d.ts" ,
1314 askStageOnEmpty : true ,
1415} )
16+
17+ // If no staged changes are found, cancel the script with a message
1518if ( ! diff ) cancel ( "no staged changes" )
1619
17- // show diff in the console
20+ // Display the diff of staged changes in the console
1821console . log ( diff )
1922
23+ // chunk if case of massive diff
24+ const chunks = await tokenizers . chunk ( diff , { chunkSize : 10000 } )
25+ if ( chunks . length > 1 )
26+ console . log ( `staged changes chunked into ${ chunks . length } parts` )
27+
2028let choice
2129let message
2230do {
23- // Generate commit message
24- const res = await runPrompt (
25- ( _ ) => {
26- _ . def ( "GIT_DIFF" , diff , { maxTokens : 20000 } )
27- _ . $ `GIT_DIFF is a diff of all staged changes, coming from the command:
28- \`\`\`
29- git diff --cached
30- \`\`\`
31- Please generate a concise, one-line commit message for these changes.
32- - do NOT add quotes
33- ` // TODO: add a better prompt
34- } ,
35- { cache : false , temperature : 0.8 }
36- )
37- if ( res . error ) throw res . error
31+ // Generate a conventional commit message based on the staged changes diff
32+ message = ""
33+ for ( const chunk of chunks ) {
34+ const res = await runPrompt (
35+ ( _ ) => {
36+ _ . def ( "GIT_DIFF" , chunk , {
37+ maxTokens : 10000 ,
38+ language : "diff" ,
39+ detectPromptInjection : "available" ,
40+ } )
41+ _ . $ `Generate a git conventional commit message that summarizes the changes in GIT_DIFF.
42+
43+ <type>: <description>
44+
45+ - <type> can be one of the following: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
46+ - <description> is a short, imperative present-tense description of the change
47+ - GIT_DIFF is generated by "git diff"
48+ - do NOT use markdown syntax
49+ - do NOT add quotes, single quote or code blocks
50+ - keep it short, 1 line only, maximum 50 characters
51+ - follow the conventional commit spec at https://www.conventionalcommits.org/en/v1.0.0/#specification
52+ - do NOT confuse delete lines starting with '-' and add lines starting with '+'
53+ `
54+ } ,
55+ {
56+ model : "large" , // Specifies the LLM model to use for message generation
57+ label : "generate commit message" , // Label for the prompt task
58+ system : [
59+ "system.assistant" ,
60+ "system.safety_jailbreak" ,
61+ "system.safety_harmful_content" ,
62+ "system.safety_validate_harmful_content" ,
63+ ] ,
64+ }
65+ )
66+ if ( res . error ) throw res . error
67+ message += res . text + "\n"
68+ }
3869
39- message = res . text
70+ // since we've concatenated the chunks, let's compress it back into a single sentence again
71+ if ( chunks . length > 1 ) {
72+ const res =
73+ await prompt `Generate a git conventional commit message that summarizes the COMMIT_MESSAGES.
74+
75+ <type>: <description>
76+
77+ - <type> can be one of the following: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
78+ - <description> is a short, imperative present-tense description of the change
79+ - do NOT use markdown syntax
80+ - do NOT add quotes or code blocks
81+ - keep it short, 1 line only, maximum 50 characters
82+ - use gitmoji
83+ - follow the conventional commit spec at https://www.conventionalcommits.org/en/v1.0.0/#specification
84+ - do NOT confuse delete lines starting with '-' and add lines starting with '+'
85+ - do NOT respond anything else than the commit message
86+
87+ COMMIT_MESSAGES:
88+ ${ message }
89+ ` . options ( {
90+ model : "large" ,
91+ label : "summarize chunk commit messages" ,
92+ system : [
93+ "system.assistant" ,
94+ "system.safety_jailbreak" ,
95+ "system.safety_harmful_content" ,
96+ "system.safety_validate_harmful_content" ,
97+ ] ,
98+ } )
99+ if ( res . error ) throw res . error
100+ message = res . text
101+ }
102+
103+ message = message ?. trim ( )
40104 if ( ! message ) {
41- console . log ( "No message generated, did you configure the LLM model?" )
105+ console . log (
106+ "No commit message generated, did you configure the LLM model?"
107+ )
42108 break
43109 }
44110
45- // Prompt user for commit message
111+ // Prompt user to accept, edit, or regenerate the commit message
46112 choice = await host . select ( message , [
47113 {
48114 value : "commit" ,
@@ -58,18 +124,19 @@ Please generate a concise, one-line commit message for these changes.
58124 } ,
59125 ] )
60126
61- // Handle user choice
127+ // Handle user's choice for commit message
62128 if ( choice === "edit" ) {
63129 message = await host . input ( "Edit commit message" , {
64130 required : true ,
65131 } )
66132 choice = "commit"
67133 }
68- // Regenerate message
134+ // If user chooses to commit, execute the git commit and optionally push changes
69135 if ( choice === "commit" && message ) {
70136 console . log ( await git . exec ( [ "commit" , "-m" , message ] ) )
71137 if ( await host . confirm ( "Push changes?" , { default : true } ) )
72138 console . log ( await git . exec ( "push" ) )
73139 break
74140 }
75141} while ( choice !== "commit" )
142+
0 commit comments