Add autocommit commit messages#4049
Add autocommit commit messages#4049nathabonfim59 wants to merge 13 commits intojesseduffield:masterfrom
Conversation
WIP(copilot): support for login with device code WIP(copilot): separate copilot client_id into const variable WIP(copilot): load AccessToken from cache WIP(copilot): login flow and chat
…ot's access token" This reverts commit 98073dc. The reason being, I just found out we can use the `RerfreshToken` from the `~/.config/github-copilot/hosts.json`.
|
I was just looking at a way to do that using custom commands, but there is no good way to use the current prompts to do that ... |
|
I have contributed an improved version of this implementation to mods (a way of using LLMs in the CLI).
But there are some interesting considerations like tokenization, we might need to discuss. I'm working in a POC. In the meantime, I hacked together a custom command integration it with LazyGit and mods that already addresses all these issues. If someone else finds it useful, here is my workflow: Important considerations
How to useFlow
Shortcuts Requirements
apis:
copilot:
base-url: https://api.githubcopilot.com
models:
gpt-4o-2024-05-13:
aliases: ["4o-2024", "4o", "gpt-4o"]
max-input-chars: 392000
gpt-4:
aliases: ["4"]
max-input-chars: 24500
gpt-3.5-turbo:
aliases: ["35t"]
max-input-chars: 12250
o1-preview-2024-09-12:
aliases: ["o1-preview", "o1p"]
max-input-chars: 128000
o1-mini-2024-09-12:
aliases: ["o1-mini", "o1m"]
max-input-chars: 128000
claude-3.5-sonnet:
aliases: ["claude3.5-sonnet", "sonnet-3.5", "claude-3-5-sonnet"]
max-input-chars: 680000Custom commands
customCommands:
- key: '<c-g>'
context: 'global'
description: 'AI Commit Message'
loadingText: 'Generating commit message'
prompts:
- type: 'menu'
title: 'AI Commit Options'
key: 'action'
options:
- name: 'Generate'
description: 'Generate new commit message'
value: 'generate'
- name: 'Commit'
description: 'Use current message'
value: 'commit'
- name: 'View'
description: 'View current message'
value: 'view'
- name: 'Clear'
description: 'Remove current message'
value: 'clear'
command: |
{{if eq .Form.action "generate"}}
gen-commit-lazygit | tee /tmp/lazygit-commit-msg
{{else if eq .Form.action "view"}}
test -f /tmp/lazygit-commit-msg && cat /tmp/lazygit-commit-msg || echo "No commit message generated yet"
{{else if eq .Form.action "clear"}}
test -f /tmp/lazygit-commit-msg && rm /tmp/lazygit-commit-msg || echo "No commit message file exists"
{{else}}
git commit -m "$(cat /tmp/lazygit-commit-msg)" && rm /tmp/lazygit-commit-msg
{{end}}
showOutput: true
- key: '<c-N>'
context: 'global'
description: 'Refine commit message'
prompts:
- type: 'input'
title: 'Enter feedback for refinement'
key: 'feedback'
command: "cat /tmp/lazygit-commit-msg | mods -q -C \"feedback: {{.Form.feedback}}\""
showOutput: trueMessage generator
#!/bin/bash
base_prompt="Create a conventional commit message for these changes. If there are multiple features or changes, list them with bullet points ('-') on separate lines. For scope, as prefix: use 'backend' for Go or other backend files, 'frontend' for Svelte or other frontend specific files, and if both are changed use the general feature scope instead. Eg: 'feat(backend/git): add new API endpoint'. If previous commits don't follow conventional format, maintain their style instead. Use the same idiom for the commit message as the previous commits"
if [ "$1" = "wip" ]; then
prompt="$base_prompt Prefix with wip() to indicate work in progress."
else
prompt="$base_prompt"
fi
context=$(
echo -e "=== Last commits ===\n"
git log -5 | sed 's/[^[:print:]]//g'
echo -e "\n=== Staged Changes ===\n"
changed_files=$(git diff --staged --name-only | sed 's/[^[:print:]]//g')
staged_changes=""
# Ignore some changes to avoid noise
# lock files, binary, in those cases, just send their names
# Define array of ignored file patterns
ignore_patterns=(".lock" ".bin" ".exe" ".dll" ".so" ".jpg" ".jpeg" ".png" ".gif" ".bmp" ".ico" ".svg" ".webp" ".mp4" ".mov" ".avi")
# Loop through each changed file
while IFS= read -r file; do
# Check if file matches any ignore pattern
should_ignore=false
for pattern in "${ignore_patterns[@]}"; do
if [[ "$file" == *"$pattern"* ]]; then
should_ignore=true
break
fi
done
if [ "$should_ignore" = true ]; then
# Just append filename for ignored files
staged_changes+="$(echo "$file" | sed 's/[^[:print:]]//g')\n"
else
# Append full diff for non-ignored files
diff=$(git diff --cached "$file" | sed 's/[^[:print:]]//g')
staged_changes+="$diff\n"
fi
done <<< "$changed_files"
# Translit to utf-8
staged_changes=$(echo "$staged_changes" | iconv -c -f utf-8 -t utf-8 | sed 's/[^[:print:]]//g')
echo -e "$staged_changes"
)
full_prompt=\
''"$prompt Just the commit message, multiple
lines if necessary . Just the commit message NOTHING ELSE. If no data is shown
or if you only see file paths with no diff content making it difficult to
understand the changes, just write the '\'\'\'' (empty string) character: '\'\'\''
<gencommit_prompt_context>
$context
</gencommit_prompt_context>
"''
message=$(echo $full_prompt | mods -q)
echo -e "$message" |
|
I'll try this next week, looks like this could work. |
|
Is there anything blocking this PR? Maybe I can help |
|
Hi, @Demianeen! I'll be backporting the changes I've made to this PR very soon, definitely this week. Initially, it will be only GitHub Copilot and OpenAI-compatible providers, but many more still to be implemented. If you're willing to test it out and provide some feedback, that would be greatly appreciated! Can I ping you back here for that? Feel free to contribute to the development as well if you're interested. |
|
@nathabonfim59 sure ping me to test |
|
Hi, any updates on this pr? |
This commit introduces a new AI service that can generate commit messages based on staged changes. The implementation includes: - Core AI service client with context building and message validation capabilities - Support for multiple AI providers (OpenAI and GitHub Copilot) with a common interface - Context builder that analyzes git state to create informative prompts for AI - Message validator to ensure generated commit messages meet quality standards - Data models defining the contract between components and providers
Add AIConfig struct with fields for enabling AI-powered commit message generation, including provider, model, API key, and other configuration options. Set default values with AI disabled by default.
…tion Add full implementation of GitHub Copilot authentication flow and API integration: - Implement device code OAuth flow for authentication - Add proper request/response structures for Copilot API - Include token management and validation - Add comprehensive error handling for API calls - Implement message extraction and sanitization
|
Do you have any updates? Thanks for this! |

PR Description
Please check if the PR fulfills these requirements
go generate ./...)This PR adds the ability to generate commit messages using AI, primarily through GitHub Copilot integration, with potential support for OpenAI-compatible APIs.
Background
This aims to implement #3763, adding AI-assisted commit message generation similar to VS Code's Copilot feature.
While the GitHub Copilot API is not officially public, the implementation doesn't appear to violate the terms of service. However, I understand introducing AI features like this may be a significant direction change for the project, so I'm open to discussion about whether this aligns with lazygit's goals.
This initial scope focuses solely on commit message generation to keep the implementation focused and manageable. Future possibilities like generating release notes, improving squash commit messages, or crafting PR descriptions could be considered later once this core functionality is proven.
The implementation is based on the flow from
ZedandCopilot.lua.I would appreciate some feedback on both the implementation approach and whether this feature could be added to the project.
Current Implementation Status
This is very much a work in progress. Just a proof of concept at the moment
Proposed configuration