diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..d9bc9cf --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,37 @@ +--- +name: Bug Report +about: Create a report to help us improve +title: '[BUG] ' +labels: bug +assignees: '' +--- + +## Bug Description +A clear and concise description of what the bug is. + +## Steps to Reproduce +1. Set environment variable '...' +2. Run command '....' +3. Observe error '....' + +## Expected Behavior +A clear and concise description of what you expected to happen. + +## Actual Behavior +What actually happened. + +## Environment +- OS: [e.g., Windows 11, macOS 14, Ubuntu 22.04] +- Go Version: [e.g., 1.23.4] +- commit-msg Version: [e.g., latest from main] +- LLM Provider: [Gemini or Grok] + +## Additional Context +Add any other context about the problem here, such as: +- Error messages +- Screenshots +- Configuration files + +## Possible Solution +If you have suggestions on how to fix the bug, please share them here. + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..2a98602 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,29 @@ +--- +name: Feature Request +about: Suggest an idea for this project +title: '[FEATURE] ' +labels: enhancement +assignees: '' +--- + +## Feature Description +A clear and concise description of the feature you'd like to see. + +## Problem It Solves +Describe the problem this feature would solve. Ex. I'm always frustrated when [...] + +## Proposed Solution +A clear and concise description of what you want to happen. + +## Alternative Solutions +Describe any alternative solutions or features you've considered. + +## Use Case +Describe how this feature would be used and who would benefit from it. + +## Additional Context +Add any other context, mockups, or screenshots about the feature request here. + +## Implementation Ideas +If you have thoughts on how this could be implemented, please share them here. + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..a2b0856 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,61 @@ +## Description + + +## Type of Change + + +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] Documentation update +- [ ] Code refactoring +- [ ] Performance improvement +- [ ] Other (please describe): + +## Related Issue + +Fixes #(issue number) + +## Changes Made + + +- +- +- + +## Testing + + +- [ ] Tested with Gemini API +- [ ] Tested with Grok API +- [ ] Tested on Windows +- [ ] Tested on Linux +- [ ] Tested on macOS +- [ ] Added/updated tests (if applicable) + +## Checklist + + +- [ ] My code follows the project's code style +- [ ] I have performed a self-review of my code +- [ ] I have commented my code, particularly in hard-to-understand areas +- [ ] I have made corresponding changes to the documentation +- [ ] My changes generate no new warnings or errors +- [ ] I have tested this in a real Git repository +- [ ] I have read the [CONTRIBUTING.md](../CONTRIBUTING.md) guidelines + +## Screenshots (if applicable) + + +## Additional Notes + + +--- + +## For Hacktoberfest Participants + + +- [ ] This PR is submitted as part of Hacktoberfest 2025 + +Thank you for your contribution! ๐ŸŽ‰ + diff --git a/.github/workflows/build-and-release.yml b/.github/workflows/build-and-release.yml new file mode 100644 index 0000000..e60aa7b --- /dev/null +++ b/.github/workflows/build-and-release.yml @@ -0,0 +1,185 @@ +name: Build and Release + +on: + push: + branches: + - main + tags: + - 'v*' + pull_request: + branches: + - main + +jobs: + auto-tag: + name: Auto Tag + runs-on: ubuntu-latest + # Only run on main branch pushes, not on tag pushes or PRs + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + outputs: + new_tag: ${{ steps.tag_version.outputs.new_tag }} + tag_created: ${{ steps.tag_version.outputs.new_tag != '' }} + permissions: + contents: write + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Auto Tag + id: tag_version + uses: mathieudutour/github-tag-action@v6.1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + default_bump: patch + create_annotated_tag: true + tag_prefix: v + + - name: Print Tag Info + run: | + echo "New tag: ${{ steps.tag_version.outputs.new_tag }}" + echo "Tag created: ${{ steps.tag_version.outputs.new_tag != '' }}" + + build: + name: Build Go Binary + runs-on: ${{ matrix.os }} + needs: auto-tag + # Always run build, even if auto-tag was skipped (e.g., for tag pushes) + if: always() && (needs.auto-tag.result == 'success' || needs.auto-tag.result == 'skipped') + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + include: + - os: ubuntu-latest + artifact_name: commit + asset_name: commit-linux-amd64 + - os: windows-latest + artifact_name: commit.exe + asset_name: commit-windows-amd64.exe + - os: macos-latest + artifact_name: commit + asset_name: commit-macos-amd64 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.23' # Use the appropriate Go version for your project + + - name: Get dependencies + run: go mod download + + - name: Build + run: | + if [ "${{ matrix.os }}" = "windows-latest" ]; then + go build -v -o ${{ matrix.artifact_name }} -ldflags="-s -w" ./src + else + go build -v -o ${{ matrix.artifact_name }} -ldflags="-s -w" ./src + fi + shell: bash + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.asset_name }} + path: ${{ matrix.artifact_name }} + + package: + name: Package Binaries + needs: [auto-tag, build] + runs-on: ubuntu-latest + # Always run after build + if: always() && needs.build.result == 'success' + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Download Linux Binary + uses: actions/download-artifact@v4 + with: + name: commit-linux-amd64 + path: ./binaries/linux + + - name: Download Windows Binary + uses: actions/download-artifact@v4 + with: + name: commit-windows-amd64.exe + path: ./binaries/windows + + - name: Download macOS Binary + uses: actions/download-artifact@v4 + with: + name: commit-macos-amd64 + path: ./binaries/macos + + - name: Show downloaded files + run: | + find ./binaries -type f + + - name: Make binaries executable + run: | + chmod +x ./binaries/linux/commit + chmod +x ./binaries/macos/commit + + - name: Create packages + run: | + mkdir -p ./packages + + # Package Linux binary + tar -C ./binaries/linux -czf ./packages/commit-linux-amd64.tar.gz commit + + # Package Windows binary + zip -j ./packages/commit-windows-amd64.zip ./binaries/windows/commit.exe + + # Package macOS binary + tar -C ./binaries/macos -czf ./packages/commit-macos-amd64.tar.gz commit + + # List created packages + ls -la ./packages/ + + - name: Upload packages as artifacts + uses: actions/upload-artifact@v4 + with: + name: release-packages + path: ./packages/* + + release: + name: Create Release + needs: [auto-tag, build, package] + # Run if a tag was created by auto-tag or this is a tag push + if: (needs.auto-tag.outputs.new_tag != '') || (github.event_name == 'push' && contains(github.ref, 'refs/tags/')) + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Download packages + uses: actions/download-artifact@v4 + with: + name: release-packages + path: ./packages + + - name: List package files + run: | + ls -la ./packages/ + + - name: Create GitHub Release + uses: softprops/action-gh-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ needs.auto-tag.outputs.new_tag != '' && needs.auto-tag.outputs.new_tag || github.ref_name }} + name: Release ${{ needs.auto-tag.outputs.new_tag != '' && needs.auto-tag.outputs.new_tag || github.ref_name }} + files: | + ./packages/commit-linux-amd64.tar.gz + ./packages/commit-windows-amd64.zip + ./packages/commit-macos-amd64.tar.gz + draft: false + prerelease: false + generate_release_notes: true \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3b735ec..2020203 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,6 @@ # Go workspace file go.work +.env +commit-helper.json +HACKTOBERFEST_SETUP.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..dc1d744 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,54 @@ +# Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Hacktoberfest Values + +This project participates in Hacktoberfest and adheres to its core values: + +* **Everyone is welcome** - We welcome participants from all backgrounds and skill levels +* **Quantity is fun, quality is key** - We prioritize meaningful contributions over volume +* **Short-term action, long-term impact** - We respect the time and effort of all contributors + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies within all project spaces, and it also applies when an individual is representing the project or its community in public spaces. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team through GitHub issues. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..514ee36 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,184 @@ +# Contributing to commit-msg + +Thank you for your interest in contributing to `commit-msg`! We welcome contributions from developers of all skill levels. ๐ŸŽ‰ + +## ๐ŸŽƒ Hacktoberfest + +This project is participating in [Hacktoberfest](https://hacktoberfest.com)! We welcome quality contributions throughout October and beyond. + +## Table of Contents + +- [Code of Conduct](#code-of-conduct) +- [How Can I Contribute?](#how-can-i-contribute) +- [Getting Started](#getting-started) +- [Development Setup](#development-setup) +- [Pull Request Process](#pull-request-process) +- [Coding Standards](#coding-standards) +- [Issue Labels](#issue-labels) + +## Code of Conduct + +This project adheres to the Hacktoberfest values: +- **Everyone is welcome** - We value diversity and inclusivity +- **Quantity is fun, quality is key** - We prioritize meaningful contributions +- **Short-term action, long-term impact** - Your contributions help build the future + +Please be respectful and constructive in all interactions. + +## How Can I Contribute? + +### ๐Ÿ› Reporting Bugs + +Before creating a bug report: +- Check the [existing issues](https://github.com/dfanso/commit-msg/issues) to avoid duplicates +- Collect information about the bug: + - OS and version + - Go version + - Steps to reproduce + - Expected vs actual behavior + +### ๐Ÿ’ก Suggesting Enhancements + +Enhancement suggestions are welcome! Please: +- Use a clear and descriptive title +- Provide a detailed description of the proposed feature +- Explain why this enhancement would be useful + +### ๐Ÿ”ง Good First Issues + +Look for issues labeled `good first issue` or `help wanted` - these are great for newcomers! + +### ๐Ÿ“ Documentation + +Improving documentation is always appreciated: +- Fix typos or unclear instructions +- Add examples +- Improve README clarity +- Translate documentation + +## Getting Started + +1. **Fork the repository** on GitHub +2. **Clone your fork** locally: + ```bash + git clone https://github.com/YOUR-USERNAME/commit-msg.git + cd commit-msg + ``` +3. **Create a branch** for your changes: + ```bash + git checkout -b feature/your-feature-name + ``` + +## Development Setup + +### Prerequisites + +- Go 1.23.4 or higher +- Git +- API key for either: + - Google Gemini (`GEMINI_API_KEY`) + - Grok (`GROK_API_KEY`) + +### Environment Setup + +1. Set up your environment variables: + ```bash + export COMMIT_LLM=gemini # or "grok" + export GEMINI_API_KEY=your-api-key-here + # OR + export GROK_API_KEY=your-api-key-here + ``` + +2. Install dependencies: + ```bash + go mod download + ``` + +3. Run the application: + ```bash + go run src/main.go . + ``` + +4. Build the executable: + ```bash + go build -o commit.exe src/main.go + ``` + +### Testing Your Changes + +Before submitting a PR: +1. Test the application in a Git repository +2. Verify both LLM providers work (if applicable) +3. Check for any errors or warnings +4. Test on your target platform + +## Pull Request Process + +1. **Update documentation** if needed (README.md, code comments) +2. **Follow the coding standards** (see below) +3. **Write clear commit messages** (ironic for this project!) +4. **Fill out the PR template** completely +5. **Link related issues** using keywords like "Fixes #123" +6. **Wait for review** - maintainers will review within 1-2 days + +### PR Title Format + +Use conventional commit format: +- `feat:` - New feature +- `fix:` - Bug fix +- `docs:` - Documentation changes +- `refactor:` - Code refactoring +- `test:` - Adding tests +- `chore:` - Maintenance tasks + +Example: `feat: add support for Claude API` + +## Coding Standards + +### Go Code Style + +- Follow [Effective Go](https://golang.org/doc/effective_go.html) guidelines +- Use `gofmt` to format your code +- Add comments for exported functions +- Keep functions small and focused +- Handle errors appropriately + +### Code Example + +```go +// GenerateMessage creates a commit message from git changes +func GenerateMessage(changes string, apiKey string) (string, error) { + if changes == "" { + return "", fmt.Errorf("no changes provided") + } + + // Implementation here + return message, nil +} +``` + +## Issue Labels + +- `good first issue` - Good for newcomers +- `help wanted` - Extra attention needed +- `bug` - Something isn't working +- `enhancement` - New feature request +- `documentation` - Documentation improvements +- `hacktoberfest` - Eligible for Hacktoberfest +- `hacktoberfest-accepted` - Approved for Hacktoberfest + +## Questions? + +Feel free to: +- Open an issue with the `question` label +- Reach out to the maintainers +- Check existing issues and PRs for similar questions + +## License + +By contributing, you agree that your contributions will be licensed under the same license as the project. + +--- + +Thank you for contributing to commit-msg! ๐Ÿš€ + diff --git a/README.md b/README.md index 38b86dd..e801ff3 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,209 @@ # commit-msg - + +[![Hacktoberfest](https://img.shields.io/badge/Hacktoberfest-2025-orange.svg)](https://hacktoberfest.com/) +[![Go Version](https://img.shields.io/badge/Go-1.23.4-blue.svg)](https://golang.org/) +[![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE) + +`commit-msg` is a command-line tool that generates commit messages using LLM (Large Language Models). It is designed to help developers create clear and concise commit messages for their Git repositories automatically by analyzing your staged changes. + +## Screenshot + +Below is a sample execution of `commit-msg`: + +![Commit-msg Screenshot](image.png) + +Before running the application, ensure you have set the system environment variables. and add commit.exe to path variables (same for linux macOS) + +## ๐ŸŽƒ Hacktoberfest 2025 + +This project is participating in **Hacktoberfest 2025**! We welcome contributions from developers of all skill levels. + +Looking to contribute? Check out: +- [Good First Issues](https://github.com/dfanso/commit-msg/labels/good%20first%20issue) +- [Help Wanted Issues](https://github.com/dfanso/commit-msg/labels/help%20wanted) +- [Contributing Guidelines](CONTRIBUTING.md) + +## Features + +โœจ **AI-Powered Commit Messages** - Automatically generate meaningful commit messages +๐Ÿ”„ **Multiple LLM Support** - Choose between Google Gemini or Grok +๐Ÿ“ **Context-Aware** - Analyzes staged and unstaged changes +๐Ÿš€ **Easy to Use** - Simple CLI interface +โšก **Fast** - Quick generation of commit messages + +## Supported LLM Providers + +You can use either **Google Gemini** or **Grok** as the LLM to generate commit messages: + +### Environment Variables + +| Variable | Values | Description | +|----------|--------|-------------| +| `COMMIT_LLM` | `gemini` or `grok` | Choose your LLM provider | +| `GEMINI_API_KEY` | Your API key | Required if using Gemini | +| `GROK_API_KEY` | Your API key | Required if using Grok | + +--- + +## ๐Ÿ“ฆ Installation + +### Option 1: Download Pre-built Binary (Recommended) + +1. Download the latest release from the [GitHub Releases](https://github.com/dfanso/commit-msg/releases) page +2. Extract the executable to a directory +3. Add the directory to your system PATH: + + **Windows:** + ```cmd + setx PATH "%PATH%;C:\path\to\commit-msg" + ``` + + **Linux/macOS:** + ```bash + export PATH=$PATH:/path/to/commit-msg + echo 'export PATH=$PATH:/path/to/commit-msg' >> ~/.bashrc # or ~/.zshrc + ``` + +4. Set up environment variables: + + **Windows:** + ```cmd + setx COMMIT_LLM "gemini" + setx GEMINI_API_KEY "your-api-key-here" + ``` + + **Linux/macOS:** + ```bash + export COMMIT_LLM=gemini + export GEMINI_API_KEY=your-api-key-here + # Add to ~/.bashrc or ~/.zshrc to persist + ``` + +### Option 2: Build from Source + +Requirements: Go 1.23.4 or higher + +```bash +# Clone the repository +git clone https://github.com/dfanso/commit-msg.git +cd commit-msg + +# Install dependencies +go mod download + +# Build the executable +go build -o commit src/main.go + +# (Optional) Install to GOPATH +go install +``` + +--- + +## ๐Ÿš€ Usage + +### Basic Usage + +Navigate to any Git repository and run: + +```bash +commit . +``` + +Or if running from source: + +```bash +go run src/main.go . +``` + +### Example Workflow + +```bash +# Make changes to your code +echo "console.log('Hello World')" > app.js + +# Stage your changes +git add . + +# Generate commit message +commit . + +# Output: "feat: add hello world console log to app.js" +``` + +### Use Cases + +- ๐Ÿ“ Generate commit messages for staged changes +- ๐Ÿ” Analyze both staged and unstaged changes +- ๐Ÿ“Š Get context from recent commits +- โœ… Create conventional commit messages + +--- + +## ๐Ÿ”ง Configuration + +### Getting API Keys + +**Google Gemini:** +1. Visit [Google AI Studio](https://makersuite.google.com/app/apikey) +2. Create a new API key +3. Set the `GEMINI_API_KEY` environment variable + +**Grok (X.AI):** +1. Visit [X.AI Console](https://console.x.ai/) +2. Generate an API key +3. Set the `GROK_API_KEY` environment variable + +--- + +## ๐Ÿค Contributing + +We welcome contributions! Please see our [Contributing Guidelines](CONTRIBUTING.md) for details. + +### Quick Start for Contributors + +1. Fork the repository +2. Create a feature branch: `git checkout -b feature/amazing-feature` +3. Make your changes +4. Commit your changes: `git commit -m 'feat: add amazing feature'` +5. Push to the branch: `git push origin feature/amazing-feature` +6. Open a Pull Request + +### Areas Where We Need Help + +- ๐Ÿ› Bug fixes +- โœจ New LLM provider integrations (OpenAI, Claude, etc.) +- ๐Ÿ“š Documentation improvements +- ๐Ÿงช Test coverage +- ๐ŸŒ Internationalization +- โšก Performance optimizations + +--- + +## ๐Ÿ“„ License + +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. + +--- + +## ๐Ÿ™ Acknowledgments + +- Thanks to all [contributors](https://github.com/dfanso/commit-msg/graphs/contributors) +- Google Gemini and X.AI Grok for providing LLM APIs +- The open-source community + +--- + +## ๐Ÿ“ž Support + +- ๐Ÿ› [Report a Bug](https://github.com/dfanso/commit-msg/issues/new?template=bug_report.md) +- ๐Ÿ’ก [Request a Feature](https://github.com/dfanso/commit-msg/issues/new?template=feature_request.md) +- ๐Ÿ’ฌ [Ask a Question](https://github.com/dfanso/commit-msg/issues) + +--- + +Made with โค๏ธ for Hacktoberfest 2025 + + + + diff --git a/go.mod b/go.mod index 6442e95..e313679 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,45 @@ module github.com/dfanso/commit-msg go 1.23.4 + +require ( + github.com/google/generative-ai-go v0.19.0 + github.com/joho/godotenv v1.5.1 +) + +require ( + cloud.google.com/go v0.115.0 // indirect + cloud.google.com/go/ai v0.8.0 // indirect + cloud.google.com/go/auth v0.15.0 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.7 // indirect + cloud.google.com/go/compute/metadata v0.6.0 // indirect + cloud.google.com/go/longrunning v0.5.7 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/google/s2a-go v0.1.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect + github.com/googleapis/gax-go/v2 v2.14.1 // indirect + go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect + go.opentelemetry.io/otel v1.34.0 // indirect + go.opentelemetry.io/otel/metric v1.34.0 // indirect + go.opentelemetry.io/otel/trace v1.34.0 // indirect + golang.org/x/crypto v0.33.0 // indirect + golang.org/x/net v0.35.0 // indirect + golang.org/x/oauth2 v0.26.0 // indirect + golang.org/x/sync v0.11.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.22.0 // indirect + golang.org/x/time v0.10.0 // indirect + google.golang.org/api v0.223.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250219182151-9fdb1cabc7b2 // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.5 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..bb22aa5 --- /dev/null +++ b/go.sum @@ -0,0 +1,211 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.115.0 h1:CnFSK6Xo3lDYRoBKEcAtia6VSC837/ZkJuRduSFnr14= +cloud.google.com/go v0.115.0/go.mod h1:8jIM5vVgoAEoiVxQ/O4BFTfHqulPZgs/ufEzMcFMdWU= +cloud.google.com/go/ai v0.8.0 h1:rXUEz8Wp2OlrM8r1bfmpF2+VKqc1VJpafE3HgzRnD/w= +cloud.google.com/go/ai v0.8.0/go.mod h1:t3Dfk4cM61sytiggo2UyGsDVW3RF1qGZaUKDrZFyqkE= +cloud.google.com/go/auth v0.6.0 h1:5x+d6b5zdezZ7gmLWD1m/xNjnaQ2YDhmIz/HH3doy1g= +cloud.google.com/go/auth v0.6.0/go.mod h1:b4acV+jLQDyjwm4OXHYjNvRi4jvGBzHWJRtJcy+2P4g= +cloud.google.com/go/auth v0.15.0 h1:Ly0u4aA5vG/fsSsxu98qCQBemXtAtJf+95z9HK+cxps= +cloud.google.com/go/auth v0.15.0/go.mod h1:WJDGqZ1o9E9wKIL+IwStfyn/+s59zl4Bi+1KQNVXLZ8= +cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4= +cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= +cloud.google.com/go/auth/oauth2adapt v0.2.7 h1:/Lc7xODdqcEw8IrZ9SvwnlLX6j9FHQM74z6cBk9Rw6M= +cloud.google.com/go/auth/oauth2adapt v0.2.7/go.mod h1:NTbTTzfvPl1Y3V1nPpOgl2w6d/FjO7NNUQaWSox6ZMc= +cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= +cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= +cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= +cloud.google.com/go/longrunning v0.5.7 h1:WLbHekDbjK1fVFD3ibpFFVoyizlLRl73I7YKuAKilhU= +cloud.google.com/go/longrunning v0.5.7/go.mod h1:8GClkudohy1Fxm3owmBGid8W0pSgodEMwEAztp38Xng= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/generative-ai-go v0.19.0 h1:R71szggh8wHMCUlEMsW2A/3T+5LdEIkiaHSYgSpUgdg= +github.com/google/generative-ai-go v0.19.0/go.mod h1:JYolL13VG7j79kM5BtHz4qwONHkeJQzOCkKXnpqtS/E= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= +github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= +github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= +github.com/googleapis/gax-go/v2 v2.12.5 h1:8gw9KZK8TiVKB6q3zHY3SBzLnrGp6HQjyfYBYGmXdxA= +github.com/googleapis/gax-go/v2 v2.12.5/go.mod h1:BUDKcWo+RaKq5SC9vVYL0wLADa3VcfswbOMMRmB9H3E= +github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q= +github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0 h1:A3SayB3rNyt+1S6qpI9mHPkeHTZbD7XILEqWnYZb2l0= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0/go.mod h1:27iA5uvhuRNmalO+iEUdVn5ZMj2qy10Mm+XRIpRmyuU= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 h1:rgMkmiGfix9vFJDcDi1PK8WEQP4FLQwLDfhp5ZLpFeE= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 h1:Xs2Ncz0gNihqu9iosIZ5SkBbWo5T8JhhLJFMQL1qmLI= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0/go.mod h1:vy+2G/6NvVMpwGX/NyLqcC41fxepnuKHk16E6IZUcJc= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= +go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= +go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= +go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= +go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= +go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= +golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE= +golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4= +golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.186.0 h1:n2OPp+PPXX0Axh4GuSsL5QL8xQCTb2oDwyzPnQvqUug= +google.golang.org/api v0.186.0/go.mod h1:hvRbBmgoje49RV3xqVXrmP6w93n6ehGgIVPYrGtBFFc= +google.golang.org/api v0.223.0 h1:JUTaWEriXmEy5AhvdMgksGGPEFsYfUKaPEYXd4c3Wvc= +google.golang.org/api v0.223.0/go.mod h1:C+RS7Z+dDwds2b+zoAk5hN/eSfsiCn0UDrYof/M4d2M= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto/googleapis/api v0.0.0-20240617180043-68d350f18fd4 h1:MuYw1wJzT+ZkybKfaOXKp5hJiZDn2iHaXRw0mRYdHSc= +google.golang.org/genproto/googleapis/api v0.0.0-20240617180043-68d350f18fd4/go.mod h1:px9SlOOZBg1wM1zdnr8jEL4CNGUBZ+ZKYtNPApNQc4c= +google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1:CkkIfIt50+lT6NHAVoRYEyAvQGFM7xEwXUUywFvEb3Q= +google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240617180043-68d350f18fd4 h1:Di6ANFilr+S60a4S61ZM00vLdw0IrQOSMS2/6mrnOU0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240617180043-68d350f18fd4/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250219182151-9fdb1cabc7b2 h1:DMTIbak9GhdaSxEjvVzAeNZvyc03I61duqNbnm3SU0M= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250219182151-9fdb1cabc7b2/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA= +google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= +google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/image.png b/image.png new file mode 100644 index 0000000..4c59a1f Binary files /dev/null and b/image.png differ diff --git a/src/gemini/gemini.go b/src/gemini/gemini.go new file mode 100644 index 0000000..b7742f1 --- /dev/null +++ b/src/gemini/gemini.go @@ -0,0 +1,55 @@ +package gemini + +import ( + "context" + "fmt" + + "github.com/google/generative-ai-go/genai" + "google.golang.org/api/option" + + "github.com/dfanso/commit-msg/src/types" +) + +type Service struct { + apiKey string + config *types.Config +} + +func NewGeminiLLM(apiKey string, config *types.Config) (types.LLM, error) { + return Service{ + apiKey: apiKey, + config: config, + }, nil +} + +func (s Service) GenerateCommitMessage(ctx context.Context, changes string) (string, error) { + // Prepare request to Google API + prompt := fmt.Sprintf("%s\n\n%s", types.CommitPrompt, changes) + + // Create context and client + client, err := genai.NewClient(ctx, option.WithAPIKey(s.apiKey)) + if err != nil { + return "", err + } + defer client.Close() + + // Create a GenerativeModel with appropriate settings + model := client.GenerativeModel("gemini-2.0-flash") + model.SetTemperature(0.2) // Lower temperature for more focused responses + + // Generate content using the prompt + resp, err := model.GenerateContent(ctx, genai.Text(prompt)) + if err != nil { + return "", err + } + + // Check if we got a valid response + if len(resp.Candidates) == 0 || len(resp.Candidates[0].Content.Parts) == 0 { + return "", fmt.Errorf("no response generated") + } + + // Extract the commit message from the response + commitMsg := fmt.Sprintf("%v", resp.Candidates[0].Content.Parts[0]) + + return commitMsg, nil +} diff --git a/src/grok/grok.go b/src/grok/grok.go new file mode 100644 index 0000000..1aa6b00 --- /dev/null +++ b/src/grok/grok.go @@ -0,0 +1,99 @@ +package grok + +import ( + "bytes" + "context" + "crypto/tls" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "time" + + "github.com/dfanso/commit-msg/src/types" +) + +type Service struct { + apiKey string + config *types.Config +} + +func NewGrokService(apiKey string, config *types.Config) (types.LLM, error) { + return Service{ + apiKey: apiKey, + config: config, + }, nil +} + +func (s Service) GenerateCommitMessage(ctx context.Context, changes string) (string, error) { + // Prepare request to X.AI (Grok) API + prompt := fmt.Sprintf("%s\n\n%s", types.CommitPrompt, changes) + + request := types.GrokRequest{ + Messages: []types.Message{ + { + Role: "user", + Content: prompt, + }, + }, + Model: "grok-3-mini-fast-beta", + Stream: false, + Temperature: 0, + } + + requestBody, err := json.Marshal(request) + if err != nil { + return "", err + } + + // Create HTTP request + req, err := http.NewRequestWithContext(ctx, "POST", "https://api.x.ai/v1/chat/completions", bytes.NewBuffer(requestBody)) + if err != nil { + return "", err + } + + // Set headers + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", s.apiKey)) + + // Configure HTTP client with improved TLS settings + transport := &http.Transport{ + TLSHandshakeTimeout: 10 * time.Second, + MaxIdleConns: 10, + IdleConnTimeout: 30 * time.Second, + DisableCompression: true, + // Add TLS config to handle server name mismatch + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: false, // Keep this false for security + }, + } + + client := &http.Client{ + Timeout: 30 * time.Second, + Transport: transport, + } + resp, err := client.Do(req) + if err != nil { + return "", err + } + defer resp.Body.Close() + + // Check response status + if resp.StatusCode != http.StatusOK { + bodyBytes, _ := ioutil.ReadAll(resp.Body) + return "", fmt.Errorf("API request failed with status %d: %s", resp.StatusCode, string(bodyBytes)) + } + + // Parse response + var grokResponse types.GrokResponse + if err := json.NewDecoder(resp.Body).Decode(&grokResponse); err != nil { + return "", err + } + + // Check if the response follows the expected structure + if grokResponse.Message.Content == "" && grokResponse.Choices != nil && len(grokResponse.Choices) > 0 { + return grokResponse.Choices[0].Message.Content, nil + } + + return grokResponse.Message.Content, nil +} diff --git a/src/main.go b/src/main.go index 29a4e10..78a77e4 100644 --- a/src/main.go +++ b/src/main.go @@ -1,7 +1,242 @@ package main -import "fmt" +import ( + "context" + "fmt" + "log" + "os" + "os/exec" + "path/filepath" + "strings" + "time" + "github.com/dfanso/commit-msg/src/gemini" + "github.com/dfanso/commit-msg/src/grok" + "github.com/dfanso/commit-msg/src/types" +) + +// Normalize path to handle both forward and backslashes +func normalizePath(path string) string { + // Replace backslashes with forward slashes + normalized := strings.ReplaceAll(path, "\\", "/") + // Remove any trailing slash + normalized = strings.TrimSuffix(normalized, "/") + return normalized +} + +// Main function func main() { - fmt.Println("Hello, Commit Message Project!") -} \ No newline at end of file + ctx := context.Background() + + // Ensure the whole process is cancelled if it takes too long. + ctx, cancel := context.WithTimeout(ctx, time.Second*10) + defer cancel() + + llmType := types.LLMType(os.Getenv("COMMIT_LLM")) + + // Get API key from environment variables + var apiKey string + switch { + case llmType == types.Google: + apiKey = os.Getenv("GOOGLE_API_KEY") + if apiKey == "" { + log.Fatalf("GOOGLE_API_KEY is not set") + } + case llmType == types.Grok: + apiKey = os.Getenv("GROK_API_KEY") + if apiKey == "" { + log.Fatalf("GROK_API_KEY is not set") + } + default: + log.Fatalf("Invalid COMMIT_LLM value: %s", llmType) + } + + // Get current directory + currentDir, err := os.Getwd() + if err != nil { + log.Fatalf("Failed to get current directory: %v", err) + } + + // Check if current directory is a git repository + if !isGitRepository(currentDir) { + log.Fatalf("Current directory is not a Git repository: %s", currentDir) + } + + // Create a minimal config for the API + config := &types.Config{ + GrokAPI: "https://api.x.ai/v1/chat/completions", + } + + // Create a repo config for the current directory + repoConfig := types.RepoConfig{ + Path: currentDir, + } + + // Get the changes + changes, err := getGitChanges(&repoConfig) + if err != nil { + log.Fatalf("Failed to get Git changes: %v", err) + } + + if len(changes) == 0 { + fmt.Println("No changes detected in the Git repository.") + return + } + + llm, err := resolveLLM(llmType, config) + if err != nil { + log.Fatalf("Failed to resolve LLM: %v", err) + } + + commitMsg, err := llm.GenerateCommitMessage(ctx, changes) + if err != nil { + log.Fatalf("Failed to generate commit message: %v", err) + } + + // Display the commit message + fmt.Println(commitMsg) +} + +// resolveLLM returns the LLM service based on the provided type. +func resolveLLM(llm types.LLMType, config *types.Config) (types.LLM, error) { + switch llm { + case types.Grok: + return grok.NewGrokService(os.Getenv("GROK_API_KEY"), config) + case types.Google: + return gemini.NewGeminiLLM(os.Getenv("GOOGLE_API_KEY"), config) + default: + return nil, fmt.Errorf("unknown LLM type %q", llm) + } +} + +// Check if directory is a git repository +func isGitRepository(path string) bool { + cmd := exec.Command("git", "-C", path, "rev-parse", "--is-inside-work-tree") + output, err := cmd.CombinedOutput() + if err != nil { + return false + } + return strings.TrimSpace(string(output)) == "true" +} + +// Get changes using Git +func getGitChanges(config *types.RepoConfig) (string, error) { + var changes strings.Builder + + // 1. Check for unstaged changes + cmd := exec.Command("git", "-C", config.Path, "diff", "--name-status") + output, err := cmd.Output() + if err != nil { + return "", fmt.Errorf("git diff failed: %v", err) + } + + if len(output) > 0 { + changes.WriteString("Unstaged changes:\n") + changes.WriteString(string(output)) + changes.WriteString("\n\n") + + // Get the content of these changes + diffCmd := exec.Command("git", "-C", config.Path, "diff") + diffOutput, err := diffCmd.Output() + if err != nil { + return "", fmt.Errorf("git diff content failed: %v", err) + } + + changes.WriteString("Unstaged diff content:\n") + changes.WriteString(string(diffOutput)) + changes.WriteString("\n\n") + } + + // 2. Check for staged changes + stagedCmd := exec.Command("git", "-C", config.Path, "diff", "--name-status", "--cached") + stagedOutput, err := stagedCmd.Output() + if err != nil { + return "", fmt.Errorf("git diff --cached failed: %v", err) + } + + if len(stagedOutput) > 0 { + changes.WriteString("Staged changes:\n") + changes.WriteString(string(stagedOutput)) + changes.WriteString("\n\n") + + // Get the content of these changes + stagedDiffCmd := exec.Command("git", "-C", config.Path, "diff", "--cached") + stagedDiffOutput, err := stagedDiffCmd.Output() + if err != nil { + return "", fmt.Errorf("git diff --cached content failed: %v", err) + } + + changes.WriteString("Staged diff content:\n") + changes.WriteString(string(stagedDiffOutput)) + changes.WriteString("\n\n") + } + + // 3. Check for untracked files + untrackedCmd := exec.Command("git", "-C", config.Path, "ls-files", "--others", "--exclude-standard") + untrackedOutput, err := untrackedCmd.Output() + if err != nil { + return "", fmt.Errorf("git ls-files failed: %v", err) + } + + if len(untrackedOutput) > 0 { + changes.WriteString("Untracked files:\n") + changes.WriteString(string(untrackedOutput)) + changes.WriteString("\n\n") + + // Try to get content of untracked files (limited to text files and smaller size) + untrackedFiles := strings.Split(strings.TrimSpace(string(untrackedOutput)), "\n") + for _, file := range untrackedFiles { + if file == "" { + continue + } + + fullPath := filepath.Join(config.Path, file) + if isTextFile(fullPath) && isSmallFile(fullPath) { + fileContent, err := os.ReadFile(fullPath) + if err == nil { + changes.WriteString(fmt.Sprintf("Content of new file %s:\n", file)) + changes.WriteString(string(fileContent)) + changes.WriteString("\n\n") + } + } + } + } + + // 4. Get recent commits for context + recentCommitsCmd := exec.Command("git", "-C", config.Path, "log", "--oneline", "-n", "3") + recentCommitsOutput, err := recentCommitsCmd.Output() + if err == nil && len(recentCommitsOutput) > 0 { + changes.WriteString("Recent commits for context:\n") + changes.WriteString(string(recentCommitsOutput)) + changes.WriteString("\n") + } + + return changes.String(), nil +} + +// Check if a file is likely to be a text file +func isTextFile(filename string) bool { + // List of common text file extensions + textExtensions := []string{".txt", ".md", ".go", ".js", ".py", ".java", ".c", ".cpp", ".h", ".html", ".css", ".json", ".xml", ".yaml", ".yml", ".sh", ".bash", ".ts", ".tsx", ".jsx", ".php", ".rb", ".rs", ".dart"} + + ext := strings.ToLower(filepath.Ext(filename)) + for _, textExt := range textExtensions { + if ext == textExt { + return true + } + } + + return false +} + +// Check if a file is small enough to include in context +func isSmallFile(filename string) bool { + const maxSize = 10 * 1024 // 10KB max + + info, err := os.Stat(filename) + if err != nil { + return false + } + + return info.Size() <= maxSize +} diff --git a/src/types/promt.go b/src/types/promt.go new file mode 100644 index 0000000..5b9a2f5 --- /dev/null +++ b/src/types/promt.go @@ -0,0 +1,19 @@ +package types + +var CommitPrompt = `I need a concise git commit message based on the following changes from my Git repository. +Please generate a commit message that: +1. Starts with a verb in the present tense (e.g., "Add", "Fix", "Update", "Feat", "Refactor", etc.) +2. Is clear and descriptive +3. Focuses on the "what" and "why" of the changes +4. Is no longer than 50-72 characters for the first line +5. Can include a more detailed description after a blank line if needed +6. Dont say any other stuff only include the commit msg + +here is a sample commit msgs: +'Feat: Add Gemini LLM support for commit messages + +- Adds Gemini as an alternative LLM for generating commit +- messages, configurable via the COMMIT_LLM environment +- variable. Also updates dependencies and README.' +Here are the changes: +` diff --git a/src/types/types.go b/src/types/types.go new file mode 100644 index 0000000..1bf661f --- /dev/null +++ b/src/types/types.go @@ -0,0 +1,65 @@ +package types + +import "context" + +// LLM abstracts the LLM api communication. +type LLM interface { + // GenerateCommitMessage generates a commit message based on the changes. + GenerateCommitMessage(ctx context.Context, changes string) (string, error) +} + +// LLMType designates a specific LLM provider. +type LLMType string + +const ( + Grok LLMType = "grok" + Google LLMType = "google" +) + +// Configuration structure +type Config struct { + GrokAPI string `json:"grok_api"` + Repos map[string]RepoConfig `json:"repos"` +} + +// Repository configuration +type RepoConfig struct { + Path string `json:"path"` + LastRun string `json:"last_run"` +} + +// Grok/X.AI API request structure +type GrokRequest struct { + Messages []Message `json:"messages"` + Model string `json:"model"` + Stream bool `json:"stream"` + Temperature float64 `json:"temperature"` +} + +type Message struct { + Role string `json:"role"` + Content string `json:"content"` +} + +// Grok/X.AI API response structure +type GrokResponse struct { + Message Message `json:"message,omitempty"` + Choices []Choice `json:"choices,omitempty"` + Id string `json:"id,omitempty"` + Object string `json:"object,omitempty"` + Created int64 `json:"created,omitempty"` + Model string `json:"model,omitempty"` + Usage UsageInfo `json:"usage,omitempty"` +} + +type Choice struct { + Message Message `json:"message"` + Index int `json:"index"` + FinishReason string `json:"finish_reason"` +} + +type UsageInfo struct { + PromptTokens int `json:"prompt_tokens"` + CompletionTokens int `json:"completion_tokens"` + TotalTokens int `json:"total_tokens"` +}