mirror of
				https://github.com/Z3Prover/z3
				synced 2025-10-31 03:32:28 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			142 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			142 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| /**
 | |
|  * Script to automate the git commit process with AI-generated commit messages.
 | |
|  * It checks for staged changes, generates a commit message, and prompts the user to review or edit the message before committing.
 | |
|  */
 | |
| 
 | |
| script({
 | |
|     title: "git commit message",
 | |
|     description: "Generate a commit message for all staged changes",
 | |
| })
 | |
| 
 | |
| // Check for staged changes and stage all changes if none are staged
 | |
| const diff = await git.diff({
 | |
|     staged: true,
 | |
|     askStageOnEmpty: true,
 | |
| })
 | |
| 
 | |
| // If no staged changes are found, cancel the script with a message
 | |
| if (!diff) cancel("no staged changes")
 | |
| 
 | |
| // Display the diff of staged changes in the console
 | |
| console.log(diff)
 | |
| 
 | |
| // chunk if case of massive diff
 | |
| const chunks = await tokenizers.chunk(diff, { chunkSize: 10000 })
 | |
| if (chunks.length > 1)
 | |
|     console.log(`staged changes chunked into ${chunks.length} parts`)
 | |
| 
 | |
| let choice
 | |
| let message
 | |
| do {
 | |
|     // Generate a conventional commit message based on the staged changes diff
 | |
|     message = ""
 | |
|     for (const chunk of chunks) {
 | |
|         const res = await runPrompt(
 | |
|             (_) => {
 | |
|                 _.def("GIT_DIFF", chunk, {
 | |
|                     maxTokens: 10000,
 | |
|                     language: "diff",
 | |
|                     detectPromptInjection: "available",
 | |
|                 })
 | |
|                 _.$`Generate a git conventional commit message that summarizes the changes in GIT_DIFF.
 | |
| 
 | |
|         <type>: <description>
 | |
| 
 | |
|         - <type> can be one of the following: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
 | |
|         - <description> is a short, imperative present-tense description of the change
 | |
|         - GIT_DIFF is generated by "git diff"
 | |
|         - do NOT use markdown syntax
 | |
|         - do NOT add quotes, single quote or code blocks
 | |
|         - keep it short, 1 line only, maximum 50 characters
 | |
|         - follow the conventional commit spec at https://www.conventionalcommits.org/en/v1.0.0/#specification
 | |
|         - do NOT confuse delete lines starting with '-' and add lines starting with '+'
 | |
|         `
 | |
|             },
 | |
|             {
 | |
|                 model: "large", // Specifies the LLM model to use for message generation
 | |
|                 label: "generate commit message", // Label for the prompt task
 | |
|                 system: [
 | |
|                     "system.assistant",
 | |
|                     "system.safety_jailbreak",
 | |
|                     "system.safety_harmful_content",
 | |
|                     "system.safety_validate_harmful_content",
 | |
|                 ],
 | |
|             }
 | |
|         )
 | |
|         if (res.error) throw res.error
 | |
|         message += res.text + "\n"
 | |
|     }
 | |
| 
 | |
|     // since we've concatenated the chunks, let's compress it back into a single sentence again
 | |
|     if (chunks.length > 1) {
 | |
|         const res =
 | |
|             await prompt`Generate a git conventional commit message that summarizes the COMMIT_MESSAGES.
 | |
| 
 | |
|         <type>: <description>
 | |
| 
 | |
|         - <type> can be one of the following: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
 | |
|         - <description> is a short, imperative present-tense description of the change
 | |
|         - do NOT use markdown syntax
 | |
|         - do NOT add quotes or code blocks
 | |
|         - keep it short, 1 line only, maximum 50 characters
 | |
|         - use gitmoji
 | |
|         - follow the conventional commit spec at https://www.conventionalcommits.org/en/v1.0.0/#specification
 | |
|         - do NOT confuse delete lines starting with '-' and add lines starting with '+'
 | |
|         - do NOT respond anything else than the commit message
 | |
| 
 | |
|         COMMIT_MESSAGES:
 | |
|         ${message}
 | |
|         `.options({
 | |
|                 model: "large",
 | |
|                 label: "summarize chunk commit messages",
 | |
|                 system: [
 | |
|                     "system.assistant",
 | |
|                     "system.safety_jailbreak",
 | |
|                     "system.safety_harmful_content",
 | |
|                     "system.safety_validate_harmful_content",
 | |
|                 ],
 | |
|             })
 | |
|         if (res.error) throw res.error
 | |
|         message = res.text
 | |
|     }
 | |
| 
 | |
|     message = message?.trim()
 | |
|     if (!message) {
 | |
|         console.log(
 | |
|             "No commit message generated, did you configure the LLM model?"
 | |
|         )
 | |
|         break
 | |
|     }
 | |
| 
 | |
|     // Prompt user to accept, edit, or regenerate the commit message
 | |
|     choice = await host.select(message, [
 | |
|         {
 | |
|             value: "commit",
 | |
|             description: "accept message and commit",
 | |
|         },
 | |
|         {
 | |
|             value: "edit",
 | |
|             description: "edit message and commit",
 | |
|         },
 | |
|         {
 | |
|             value: "regenerate",
 | |
|             description: "regenerate message",
 | |
|         },
 | |
|     ])
 | |
| 
 | |
|     // Handle user's choice for commit message
 | |
|     if (choice === "edit") {
 | |
|         message = await host.input("Edit commit message", {
 | |
|             required: true,
 | |
|         })
 | |
|         choice = "commit"
 | |
|     }
 | |
|     // If user chooses to commit, execute the git commit and optionally push changes
 | |
|     if (choice === "commit" && message) {
 | |
|         console.log(await git.exec(["commit", "-m", message]))
 | |
|         if (await host.confirm("Push changes?", { default: true }))
 | |
|             console.log(await git.exec("push"))
 | |
|         break
 | |
|     }
 | |
| } while (choice !== "commit")
 | |
| 
 |