mirror of
				https://github.com/Z3Prover/z3
				synced 2025-11-04 05:19:11 +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")
 | 
						|
 |