update
All checks were successful
Enterprise AI Code Review / ai-review (pull_request) Successful in 32s
All checks were successful
Enterprise AI Code Review / ai-review (pull_request) Successful in 32s
This commit is contained in:
@@ -1,36 +1,37 @@
|
|||||||
name: AI Issue Triage
|
name: AI Issue Triage
|
||||||
|
|
||||||
on:
|
on:
|
||||||
issues:
|
issue_comment:
|
||||||
types: [opened, labeled]
|
types: [created]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ai-triage:
|
ai-triage:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
# Only run if comment contains @codebot triage
|
||||||
- uses: actions/checkout@v4
|
if: contains(github.event.comment.body, '@codebot triage')
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
repository: Hiddenden/openrabbit
|
repository: Hiddenden/openrabbit
|
||||||
path: .ai-review
|
path: .ai-review
|
||||||
token: ${{ secrets.AI_REVIEW_TOKEN }}
|
token: ${{ secrets.AI_REVIEW_TOKEN }}
|
||||||
|
|
||||||
- uses: actions/setup-python@v5
|
- uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: "3.11"
|
python-version: "3.11"
|
||||||
|
|
||||||
- run: pip install requests pyyaml
|
- run: pip install requests pyyaml
|
||||||
|
|
||||||
- name: Run AI Issue Triage
|
- name: Run AI Issue Triage
|
||||||
env:
|
env:
|
||||||
AI_REVIEW_TOKEN: ${{ secrets.AI_REVIEW_TOKEN }}
|
AI_REVIEW_TOKEN: ${{ secrets.AI_REVIEW_TOKEN }}
|
||||||
AI_REVIEW_REPO: ${{ gitea.repository }}
|
AI_REVIEW_REPO: ${{ gitea.repository }}
|
||||||
AI_REVIEW_API_URL: https://git.hiddenden.cafe/api/v1
|
AI_REVIEW_API_URL: https://git.hiddenden.cafe/api/v1
|
||||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||||
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
|
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
|
||||||
OLLAMA_HOST: ${{ secrets.OLLAMA_HOST }}
|
OLLAMA_HOST: ${{ secrets.OLLAMA_HOST }}
|
||||||
run: |
|
run: |
|
||||||
cd .ai-review/tools/ai-review
|
cd .ai-review/tools/ai-review
|
||||||
python main.py issue ${{ gitea.repository }} ${{ gitea.event.issue.number }} \
|
python main.py issue ${{ gitea.repository }} ${{ gitea.event.issue.number }}
|
||||||
--title "${{ gitea.event.issue.title }}"
|
|
||||||
|
|||||||
36
.github/workflows/ai-chat.yml
vendored
36
.github/workflows/ai-chat.yml
vendored
@@ -1,36 +0,0 @@
|
|||||||
name: AI Chat (Bartender)
|
|
||||||
|
|
||||||
on:
|
|
||||||
issue_comment:
|
|
||||||
types: [created]
|
|
||||||
|
|
||||||
# CUSTOMIZE YOUR BOT NAME:
|
|
||||||
# Change '@ai-bot' below to match your config.yml mention_prefix
|
|
||||||
# Examples: '@bartender', '@uni', '@joey', '@codebot'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
ai-chat:
|
|
||||||
# Only run if comment mentions the bot
|
|
||||||
if: contains(github.event.comment.body, '@bartender') # <-- Change this to your bot name
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: "3.11"
|
|
||||||
|
|
||||||
- run: pip install requests pyyaml
|
|
||||||
|
|
||||||
- name: Run AI Chat
|
|
||||||
env:
|
|
||||||
AI_REVIEW_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
AI_REVIEW_REPO: ${{ github.repository }}
|
|
||||||
AI_REVIEW_API_URL: https://api.github.com
|
|
||||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
||||||
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
|
|
||||||
OLLAMA_HOST: ${{ secrets.OLLAMA_HOST }}
|
|
||||||
SEARXNG_URL: ${{ secrets.SEARXNG_URL }}
|
|
||||||
run: |
|
|
||||||
cd tools/ai-review
|
|
||||||
python main.py comment ${{ github.repository }} ${{ github.event.issue.number }} "${{ github.event.comment.body }}"
|
|
||||||
51
.github/workflows/ai-codebase-review.yml
vendored
51
.github/workflows/ai-codebase-review.yml
vendored
@@ -1,51 +0,0 @@
|
|||||||
name: AI Codebase Quality Review
|
|
||||||
|
|
||||||
on:
|
|
||||||
# Weekly scheduled run
|
|
||||||
schedule:
|
|
||||||
- cron: "0 0 * * 0" # Every Sunday at midnight
|
|
||||||
|
|
||||||
# Manual trigger
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
report_type:
|
|
||||||
description: "Type of report to generate"
|
|
||||||
required: false
|
|
||||||
default: "full"
|
|
||||||
type: choice
|
|
||||||
options:
|
|
||||||
- full
|
|
||||||
- security
|
|
||||||
- quick
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
ai-codebase-review:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
# Checkout the repository
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0 # Full history for analysis
|
|
||||||
|
|
||||||
# Setup Python
|
|
||||||
- uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: "3.11"
|
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
- run: pip install requests pyyaml
|
|
||||||
|
|
||||||
# Run AI codebase analysis
|
|
||||||
- name: Run AI Codebase Analysis
|
|
||||||
env:
|
|
||||||
AI_REVIEW_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
AI_REVIEW_REPO: ${{ github.repository }}
|
|
||||||
AI_REVIEW_API_URL: https://api.github.com
|
|
||||||
|
|
||||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
||||||
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
|
|
||||||
OLLAMA_HOST: ${{ secrets.OLLAMA_HOST }}
|
|
||||||
run: |
|
|
||||||
cd tools/ai-review
|
|
||||||
python main.py codebase ${{ github.repository }}
|
|
||||||
36
.github/workflows/ai-comment-reply.yml
vendored
36
.github/workflows/ai-comment-reply.yml
vendored
@@ -1,36 +0,0 @@
|
|||||||
name: AI Comment Reply
|
|
||||||
|
|
||||||
on:
|
|
||||||
issue_comment:
|
|
||||||
types: [created]
|
|
||||||
|
|
||||||
# CUSTOMIZE YOUR BOT NAME:
|
|
||||||
# Change '@ai-bot' below to match your config.yml mention_prefix
|
|
||||||
# Examples: '@bartender', '@uni', '@joey', '@codebot'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
ai-reply:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: contains(github.event.comment.body, '@bartender') # <-- Change this to your bot name
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: "3.11"
|
|
||||||
|
|
||||||
- run: pip install requests pyyaml
|
|
||||||
|
|
||||||
- name: Run AI Comment Response
|
|
||||||
env:
|
|
||||||
AI_REVIEW_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
AI_REVIEW_REPO: ${{ github.repository }}
|
|
||||||
AI_REVIEW_API_URL: https://api.github.com
|
|
||||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
||||||
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
|
|
||||||
OLLAMA_HOST: ${{ secrets.OLLAMA_HOST }}
|
|
||||||
SEARXNG_URL: ${{ secrets.SEARXNG_URL }}
|
|
||||||
run: |
|
|
||||||
cd tools/ai-review
|
|
||||||
python main.py comment ${{ github.repository }} ${{ github.event.issue.number }} \
|
|
||||||
"${{ github.event.comment.body }}"
|
|
||||||
30
.github/workflows/ai-issue-triage.yml
vendored
30
.github/workflows/ai-issue-triage.yml
vendored
@@ -1,30 +0,0 @@
|
|||||||
name: AI Issue Triage
|
|
||||||
|
|
||||||
on:
|
|
||||||
issues:
|
|
||||||
types: [opened, labeled]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
ai-triage:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: "3.11"
|
|
||||||
|
|
||||||
- run: pip install requests pyyaml
|
|
||||||
|
|
||||||
- name: Run AI Issue Triage
|
|
||||||
env:
|
|
||||||
AI_REVIEW_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
AI_REVIEW_REPO: ${{ github.repository }}
|
|
||||||
AI_REVIEW_API_URL: https://api.github.com
|
|
||||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
||||||
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
|
|
||||||
OLLAMA_HOST: ${{ secrets.OLLAMA_HOST }}
|
|
||||||
run: |
|
|
||||||
cd tools/ai-review
|
|
||||||
python main.py issue ${{ github.repository }} ${{ github.event.issue.number }} \
|
|
||||||
--title "${{ github.event.issue.title }}"
|
|
||||||
52
.github/workflows/ai-review.yml
vendored
52
.github/workflows/ai-review.yml
vendored
@@ -1,52 +0,0 @@
|
|||||||
name: AI Code Review
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
ai-review:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
# Checkout the PR repository
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
# Checkout the AI tooling from this repo's tools directory
|
|
||||||
- name: Setup AI Review Tools
|
|
||||||
run: |
|
|
||||||
# Tools are already in this repo under tools/ai-review
|
|
||||||
echo "AI Review tools available at tools/ai-review"
|
|
||||||
|
|
||||||
# Setup Python
|
|
||||||
- uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: "3.11"
|
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
- run: pip install requests pyyaml
|
|
||||||
|
|
||||||
# Run the AI review
|
|
||||||
- name: Run AI Review
|
|
||||||
env:
|
|
||||||
AI_REVIEW_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
AI_REVIEW_REPO: ${{ github.repository }}
|
|
||||||
AI_REVIEW_API_URL: https://api.github.com
|
|
||||||
AI_REVIEW_PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
||||||
|
|
||||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
||||||
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
|
|
||||||
OLLAMA_HOST: ${{ secrets.OLLAMA_HOST }}
|
|
||||||
run: |
|
|
||||||
cd tools/ai-review
|
|
||||||
python main.py pr ${{ github.repository }} ${{ github.event.pull_request.number }} \
|
|
||||||
--title "${{ github.event.pull_request.title }}"
|
|
||||||
|
|
||||||
# Fail CI on HIGH severity (optional)
|
|
||||||
- name: Check Review Result
|
|
||||||
if: failure()
|
|
||||||
run: |
|
|
||||||
echo "AI Review found HIGH severity issues. Please address them before merging."
|
|
||||||
exit 1
|
|
||||||
347
CLAUDE.md
Normal file
347
CLAUDE.md
Normal file
@@ -0,0 +1,347 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
OpenRabbit is an enterprise-grade AI code review system for Gitea (and GitHub). It provides automated PR review, issue triage, interactive chat, and codebase analysis through a collection of specialized AI agents.
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
### Development
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run tests
|
||||||
|
pytest tests/ -v
|
||||||
|
|
||||||
|
# Run specific test file
|
||||||
|
pytest tests/test_ai_review.py -v
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
pip install -r tools/ai-review/requirements.txt
|
||||||
|
|
||||||
|
# Run a PR review locally
|
||||||
|
cd tools/ai-review
|
||||||
|
python main.py pr owner/repo 123
|
||||||
|
|
||||||
|
# Run issue triage
|
||||||
|
python main.py issue owner/repo 456
|
||||||
|
|
||||||
|
# Test chat functionality
|
||||||
|
python main.py chat owner/repo "How does authentication work?"
|
||||||
|
|
||||||
|
# Run with custom config
|
||||||
|
python main.py pr owner/repo 123 --config /path/to/config.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testing Workflows
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Validate workflow YAML syntax
|
||||||
|
python -c "import yaml; yaml.safe_load(open('.github/workflows/ai-review.yml'))"
|
||||||
|
|
||||||
|
# Test security scanner
|
||||||
|
python -c "from security.security_scanner import SecurityScanner; s = SecurityScanner(); print(list(s.scan_content('password = \"secret123\"', 'test.py')))"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Agent System
|
||||||
|
|
||||||
|
The codebase uses an **agent-based architecture** where specialized agents handle different types of events:
|
||||||
|
|
||||||
|
1. **BaseAgent** (`agents/base_agent.py`) - Abstract base class providing:
|
||||||
|
- Gitea API client integration
|
||||||
|
- LLM client integration with rate limiting
|
||||||
|
- Common comment management (upsert, find AI comments)
|
||||||
|
- Prompt loading from `prompts/` directory
|
||||||
|
- Standard execution flow with error handling
|
||||||
|
|
||||||
|
2. **Specialized Agents** - Each agent implements:
|
||||||
|
- `can_handle(event_type, event_data)` - Determines if agent should process the event
|
||||||
|
- `execute(context)` - Main execution logic
|
||||||
|
- Returns `AgentResult` with success status, message, data, and actions taken
|
||||||
|
|
||||||
|
- **PRAgent** - Reviews pull requests with inline comments and security scanning
|
||||||
|
- **IssueAgent** - Triages issues and responds to @ai-bot commands
|
||||||
|
- **CodebaseAgent** - Analyzes entire codebase health and tech debt
|
||||||
|
- **ChatAgent** - Interactive assistant with tool calling (search_codebase, read_file, search_web)
|
||||||
|
|
||||||
|
3. **Dispatcher** (`dispatcher.py`) - Routes events to appropriate agents:
|
||||||
|
- Registers agents at startup
|
||||||
|
- Determines which agents can handle each event
|
||||||
|
- Executes agents (supports concurrent execution)
|
||||||
|
- Returns aggregated results
|
||||||
|
|
||||||
|
### Multi-Provider LLM Client
|
||||||
|
|
||||||
|
The `LLMClient` (`clients/llm_client.py`) provides a unified interface for multiple LLM providers:
|
||||||
|
|
||||||
|
- **OpenAI** - Primary provider (gpt-4.1-mini default)
|
||||||
|
- **OpenRouter** - Multi-provider access (claude-3.5-sonnet)
|
||||||
|
- **Ollama** - Self-hosted models (codellama:13b)
|
||||||
|
|
||||||
|
Key features:
|
||||||
|
- Tool/function calling support via `call_with_tools(messages, tools)`
|
||||||
|
- JSON response parsing with fallback extraction
|
||||||
|
- Provider-specific configuration via `config.yml`
|
||||||
|
|
||||||
|
### Platform Abstraction
|
||||||
|
|
||||||
|
The `GiteaClient` (`clients/gitea_client.py`) provides a unified REST API client for **Gitea** (also compatible with GitHub API):
|
||||||
|
|
||||||
|
- Issue operations (create, update, list, get, comments, labels)
|
||||||
|
- PR operations (get, diff, files, reviews)
|
||||||
|
- Repository operations (get repo, file contents, branches)
|
||||||
|
|
||||||
|
Environment variables:
|
||||||
|
- `AI_REVIEW_API_URL` - API base URL (e.g., `https://api.github.com` or `https://gitea.example.com/api/v1`)
|
||||||
|
- `AI_REVIEW_TOKEN` - Authentication token
|
||||||
|
|
||||||
|
### Security Scanner
|
||||||
|
|
||||||
|
The `SecurityScanner` (`security/security_scanner.py`) uses **pattern-based detection** with 17 built-in rules covering:
|
||||||
|
|
||||||
|
- OWASP Top 10 categories (A01-A10)
|
||||||
|
- Common vulnerabilities (SQL injection, XSS, hardcoded secrets, weak crypto)
|
||||||
|
- Returns `SecurityFinding` objects with severity (HIGH/MEDIUM/LOW), CWE references, and recommendations
|
||||||
|
|
||||||
|
Can scan:
|
||||||
|
- File content via `scan_content(content, filename)`
|
||||||
|
- Git diffs via `scan_diff(diff)` - only scans added lines
|
||||||
|
|
||||||
|
### Chat Agent Tool Calling
|
||||||
|
|
||||||
|
The `ChatAgent` implements an **iterative tool calling loop**:
|
||||||
|
|
||||||
|
1. Send user message + system prompt to LLM with available tools
|
||||||
|
2. If LLM returns tool calls, execute each tool and append results to conversation
|
||||||
|
3. Repeat until LLM returns a final response (max 5 iterations)
|
||||||
|
|
||||||
|
Available tools:
|
||||||
|
- `search_codebase` - Searches repository files and code patterns
|
||||||
|
- `read_file` - Reads specific file contents (truncated at 8KB)
|
||||||
|
- `search_web` - Queries SearXNG instance (requires `SEARXNG_URL`)
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Primary Config File: `tools/ai-review/config.yml`
|
||||||
|
|
||||||
|
Critical settings:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
provider: openai # openai | openrouter | ollama
|
||||||
|
|
||||||
|
model:
|
||||||
|
openai: gpt-4.1-mini
|
||||||
|
openrouter: anthropic/claude-3.5-sonnet
|
||||||
|
ollama: codellama:13b
|
||||||
|
|
||||||
|
interaction:
|
||||||
|
mention_prefix: "@codebot" # Bot trigger name - update workflows too!
|
||||||
|
commands:
|
||||||
|
- explain # Explain what the issue is about
|
||||||
|
- suggest # Suggest solutions or next steps
|
||||||
|
- security # Security analysis
|
||||||
|
- summarize # Summarize the issue
|
||||||
|
- triage # Full triage with labeling
|
||||||
|
|
||||||
|
review:
|
||||||
|
fail_on_severity: HIGH # Fail CI if HIGH severity issues found
|
||||||
|
max_diff_lines: 800 # Skip review if diff too large
|
||||||
|
|
||||||
|
agents:
|
||||||
|
chat:
|
||||||
|
max_iterations: 5 # Tool calling loop limit
|
||||||
|
```
|
||||||
|
|
||||||
|
**Important**: When changing `mention_prefix`, also update all workflow files in `.gitea/workflows/`:
|
||||||
|
- `ai-comment-reply.yml`
|
||||||
|
- `ai-chat.yml`
|
||||||
|
- `ai-issue-triage.yml`
|
||||||
|
|
||||||
|
Look for: `if: contains(github.event.comment.body, '@codebot')` and update to your new bot name.
|
||||||
|
|
||||||
|
Current bot name: `@codebot`
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
Required:
|
||||||
|
- `AI_REVIEW_API_URL` - Platform API URL
|
||||||
|
- `AI_REVIEW_TOKEN` - Bot authentication token
|
||||||
|
- `OPENAI_API_KEY` - OpenAI API key (or provider-specific key)
|
||||||
|
|
||||||
|
Optional:
|
||||||
|
- `SEARXNG_URL` - SearXNG instance for web search
|
||||||
|
- `OPENROUTER_API_KEY` - OpenRouter API key
|
||||||
|
- `OLLAMA_HOST` - Ollama server URL
|
||||||
|
|
||||||
|
## Workflow Architecture
|
||||||
|
|
||||||
|
Workflows are located in `.gitea/workflows/`:
|
||||||
|
|
||||||
|
- **ai-review.yml** / **enterprise-ai-review.yml** - Triggered on PR open/sync
|
||||||
|
- **ai-issue-triage.yml** - Triggered on `@codebot triage` mention in issue comments
|
||||||
|
- **ai-comment-reply.yml** - Triggered on issue comments with @bot mentions
|
||||||
|
- **ai-chat.yml** - Triggered on issue comments for chat (non-command mentions)
|
||||||
|
- **ai-codebase-review.yml** - Scheduled weekly analysis
|
||||||
|
|
||||||
|
**Note**: Issue triage is now **opt-in** via `@codebot triage` command, not automatic on issue creation.
|
||||||
|
|
||||||
|
Key workflow pattern:
|
||||||
|
1. Checkout repository
|
||||||
|
2. Setup Python 3.11
|
||||||
|
3. Install dependencies (`pip install requests pyyaml`)
|
||||||
|
4. Set environment variables
|
||||||
|
5. Run `python main.py <command> <args>`
|
||||||
|
|
||||||
|
## Prompt Templates
|
||||||
|
|
||||||
|
Prompts are stored in `tools/ai-review/prompts/` as Markdown files:
|
||||||
|
|
||||||
|
- `base.md` - Base instructions for all reviews
|
||||||
|
- `issue_triage.md` - Issue classification template
|
||||||
|
- `issue_response.md` - Issue response template
|
||||||
|
|
||||||
|
**Important**: JSON examples in prompts must use **double curly braces** (`{{` and `}}`) to escape Python's `.format()` method. This is tested in `tests/test_ai_review.py::TestPromptFormatting`.
|
||||||
|
|
||||||
|
## Code Patterns
|
||||||
|
|
||||||
|
### Creating a New Agent
|
||||||
|
|
||||||
|
```python
|
||||||
|
from agents.base_agent import BaseAgent, AgentContext, AgentResult
|
||||||
|
|
||||||
|
class MyAgent(BaseAgent):
|
||||||
|
def can_handle(self, event_type: str, event_data: dict) -> bool:
|
||||||
|
# Check if agent is enabled in config
|
||||||
|
if not self.config.get("agents", {}).get("my_agent", {}).get("enabled", True):
|
||||||
|
return False
|
||||||
|
return event_type == "my_event_type"
|
||||||
|
|
||||||
|
def execute(self, context: AgentContext) -> AgentResult:
|
||||||
|
# Load prompt template
|
||||||
|
prompt = self.load_prompt("my_prompt")
|
||||||
|
formatted = prompt.format(data=context.event_data.get("field"))
|
||||||
|
|
||||||
|
# Call LLM with rate limiting
|
||||||
|
response = self.call_llm(formatted)
|
||||||
|
|
||||||
|
# Post comment to issue/PR
|
||||||
|
self.upsert_comment(
|
||||||
|
context.owner,
|
||||||
|
context.repo,
|
||||||
|
issue_index,
|
||||||
|
response.content
|
||||||
|
)
|
||||||
|
|
||||||
|
return AgentResult(
|
||||||
|
success=True,
|
||||||
|
message="Agent completed",
|
||||||
|
actions_taken=["Posted comment"]
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Calling LLM with Tools
|
||||||
|
|
||||||
|
```python
|
||||||
|
messages = [
|
||||||
|
{"role": "system", "content": "You are a helpful assistant"},
|
||||||
|
{"role": "user", "content": "Search for authentication code"}
|
||||||
|
]
|
||||||
|
|
||||||
|
tools = [{
|
||||||
|
"type": "function",
|
||||||
|
"function": {
|
||||||
|
"name": "search_code",
|
||||||
|
"description": "Search codebase",
|
||||||
|
"parameters": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {"query": {"type": "string"}},
|
||||||
|
"required": ["query"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
|
||||||
|
response = self.llm.call_with_tools(messages, tools=tools)
|
||||||
|
|
||||||
|
if response.tool_calls:
|
||||||
|
for tc in response.tool_calls:
|
||||||
|
result = execute_tool(tc.name, tc.arguments)
|
||||||
|
messages.append({
|
||||||
|
"role": "tool",
|
||||||
|
"tool_call_id": tc.id,
|
||||||
|
"content": result
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Adding Security Rules
|
||||||
|
|
||||||
|
Edit `tools/ai-review/security/security_scanner.py` or create `security/security_rules.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
rules:
|
||||||
|
- id: SEC018
|
||||||
|
name: Custom Rule Name
|
||||||
|
pattern: 'regex_pattern_here'
|
||||||
|
severity: HIGH # HIGH, MEDIUM, LOW
|
||||||
|
category: A03:2021 Injection
|
||||||
|
cwe: CWE-XXX
|
||||||
|
description: What this detects
|
||||||
|
recommendation: How to fix it
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
The test suite (`tests/test_ai_review.py`) covers:
|
||||||
|
|
||||||
|
1. **Prompt Formatting** - Ensures prompts don't have unescaped `{}` that break `.format()`
|
||||||
|
2. **Module Imports** - Verifies all modules can be imported
|
||||||
|
3. **Security Scanner** - Tests pattern detection and false positive rate
|
||||||
|
4. **Agent Context** - Tests dataclass creation and validation
|
||||||
|
5. **Metrics** - Tests enterprise metrics collection
|
||||||
|
|
||||||
|
Run specific test classes:
|
||||||
|
```bash
|
||||||
|
pytest tests/test_ai_review.py::TestPromptFormatting -v
|
||||||
|
pytest tests/test_ai_review.py::TestSecurityScanner -v
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Development Tasks
|
||||||
|
|
||||||
|
### Adding a New Command to @codebot
|
||||||
|
|
||||||
|
1. Add command to `config.yml` under `interaction.commands`
|
||||||
|
2. Add handler method in `IssueAgent` (e.g., `_command_yourcommand()`)
|
||||||
|
3. Update `_handle_command()` to route the command to your handler
|
||||||
|
4. Update README.md with command documentation
|
||||||
|
5. Add tests in `tests/test_ai_review.py`
|
||||||
|
|
||||||
|
Example commands:
|
||||||
|
- `@codebot triage` - Full issue triage with labeling
|
||||||
|
- `@codebot explain` - Explain the issue
|
||||||
|
- `@codebot suggest` - Suggest solutions
|
||||||
|
|
||||||
|
### Changing the Bot Name
|
||||||
|
|
||||||
|
1. Edit `config.yml`: `interaction.mention_prefix: "@newname"`
|
||||||
|
2. Update all Gitea workflow files in `.gitea/workflows/` (search for `contains(github.event.comment.body`)
|
||||||
|
3. Update README.md and documentation
|
||||||
|
|
||||||
|
### Supporting a New LLM Provider
|
||||||
|
|
||||||
|
1. Create provider class in `clients/llm_client.py` inheriting from `BaseLLMProvider`
|
||||||
|
2. Implement `call()` and optionally `call_with_tools()`
|
||||||
|
3. Register in `LLMClient.PROVIDERS` dict
|
||||||
|
4. Add model config to `config.yml`
|
||||||
|
5. Document in README.md
|
||||||
|
|
||||||
|
## Repository Labels
|
||||||
|
|
||||||
|
The system expects these labels to exist in repositories for auto-labeling:
|
||||||
|
|
||||||
|
- `priority: high`, `priority: medium`, `priority: low`
|
||||||
|
- `type: bug`, `type: feature`, `type: question`, `type: documentation`
|
||||||
|
- `ai-approved`, `ai-changes-required`, `ai-reviewed`
|
||||||
|
|
||||||
|
Labels are mapped in `config.yml` under the `labels` section.
|
||||||
118
README.md
118
README.md
@@ -1,6 +1,6 @@
|
|||||||
# OpenRabbit
|
# OpenRabbit
|
||||||
|
|
||||||
Enterprise-grade AI code review system for **GitHub** and **Gitea** with automated PR review, issue triage, interactive chat (Bartender), and codebase analysis.
|
Enterprise-grade AI code review system for **Gitea** with automated PR review, issue triage, interactive chat, and codebase analysis.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -9,13 +9,13 @@ Enterprise-grade AI code review system for **GitHub** and **Gitea** with automat
|
|||||||
| Feature | Description |
|
| Feature | Description |
|
||||||
|---------|-------------|
|
|---------|-------------|
|
||||||
| **PR Review** | Inline comments, security scanning, severity-based CI failure |
|
| **PR Review** | Inline comments, security scanning, severity-based CI failure |
|
||||||
| **Issue Triage** | Auto-classification, labeling, priority assignment |
|
| **Issue Triage** | On-demand classification, labeling, priority assignment via `@codebot triage` |
|
||||||
| **Chat (Bartender)** | Interactive AI chat with codebase search and web search tools |
|
| **Chat** | Interactive AI chat with codebase search and web search tools |
|
||||||
| **@ai-bot Commands** | `@ai-bot summarize`, `explain`, `suggest` in issue comments |
|
| **@codebot Commands** | `@codebot summarize`, `explain`, `suggest`, `triage` in issue comments |
|
||||||
| **Codebase Analysis** | Health scores, tech debt tracking, weekly reports |
|
| **Codebase Analysis** | Health scores, tech debt tracking, weekly reports |
|
||||||
| **Security Scanner** | 17 OWASP-aligned rules for vulnerability detection |
|
| **Security Scanner** | 17 OWASP-aligned rules for vulnerability detection |
|
||||||
| **Enterprise Ready** | Audit logging, metrics, Prometheus export |
|
| **Enterprise Ready** | Audit logging, metrics, Prometheus export |
|
||||||
| **Multi-Platform** | Works with both GitHub and Gitea |
|
| **Gitea Native** | Built for Gitea workflows and API |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -38,49 +38,14 @@ The built-in `GITHUB_TOKEN` is used automatically.
|
|||||||
|
|
||||||
### 2. Add Workflows to Repository
|
### 2. Add Workflows to Repository
|
||||||
|
|
||||||
Workflows are provided for both platforms:
|
Workflows are located in `.gitea/workflows/`.
|
||||||
|
|
||||||
| Platform | Location |
|
|
||||||
|----------|----------|
|
|
||||||
| GitHub | `.github/workflows/` |
|
|
||||||
| Gitea | `.gitea/workflows/` |
|
|
||||||
|
|
||||||
#### GitHub Example
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
# .github/workflows/ai-review.yml
|
|
||||||
name: AI PR Review
|
|
||||||
on: [pull_request]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
ai-review:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: "3.11"
|
|
||||||
|
|
||||||
- run: pip install requests pyyaml
|
|
||||||
|
|
||||||
- name: Run AI Review
|
|
||||||
env:
|
|
||||||
AI_REVIEW_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
AI_REVIEW_REPO: ${{ github.repository }}
|
|
||||||
AI_REVIEW_API_URL: https://api.github.com
|
|
||||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
||||||
run: |
|
|
||||||
cd tools/ai-review
|
|
||||||
python main.py pr ${{ github.repository }} ${{ github.event.pull_request.number }}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Gitea Example
|
#### Gitea Example
|
||||||
|
|
||||||
|
#### Gitea PR Review Workflow
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# .gitea/workflows/ai-review.yml
|
# .gitea/workflows/enterprise-ai-review.yml
|
||||||
name: AI PR Review
|
name: AI PR Review
|
||||||
on: [pull_request]
|
on: [pull_request]
|
||||||
|
|
||||||
@@ -115,7 +80,7 @@ jobs:
|
|||||||
python main.py pr ${{ gitea.repository }} ${{ gitea.event.pull_request.number }}
|
python main.py pr ${{ gitea.repository }} ${{ gitea.event.pull_request.number }}
|
||||||
```
|
```
|
||||||
|
|
||||||
For full workflow examples, see [Workflows Documentation](docs/workflows.md).
|
See `.gitea/workflows/` for all workflow examples.
|
||||||
|
|
||||||
### 3. Create Labels
|
### 3. Create Labels
|
||||||
|
|
||||||
@@ -132,10 +97,10 @@ Create these labels in your repository for auto-labeling:
|
|||||||
tools/ai-review/
|
tools/ai-review/
|
||||||
├── agents/ # Agent implementations
|
├── agents/ # Agent implementations
|
||||||
│ ├── base_agent.py # Abstract base agent
|
│ ├── base_agent.py # Abstract base agent
|
||||||
│ ├── issue_agent.py # Issue triage & @ai-bot commands
|
│ ├── issue_agent.py # Issue triage & @codebot commands
|
||||||
│ ├── pr_agent.py # PR review with security scan
|
│ ├── pr_agent.py # PR review with security scan
|
||||||
│ ├── codebase_agent.py # Codebase health analysis
|
│ ├── codebase_agent.py # Codebase health analysis
|
||||||
│ └── chat_agent.py # Bartender chat with tool calling
|
│ └── chat_agent.py # Interactive chat with tool calling
|
||||||
├── clients/ # API clients
|
├── clients/ # API clients
|
||||||
│ ├── gitea_client.py # Gitea REST API wrapper
|
│ ├── gitea_client.py # Gitea REST API wrapper
|
||||||
│ └── llm_client.py # Multi-provider LLM client with tool support
|
│ └── llm_client.py # Multi-provider LLM client with tool support
|
||||||
@@ -152,8 +117,8 @@ tools/ai-review/
|
|||||||
├── ai-review.yml # PR review workflow
|
├── ai-review.yml # PR review workflow
|
||||||
├── ai-issue-triage.yml # Issue triage workflow
|
├── ai-issue-triage.yml # Issue triage workflow
|
||||||
├── ai-codebase-review.yml # Codebase analysis
|
├── ai-codebase-review.yml # Codebase analysis
|
||||||
├── ai-comment-reply.yml # @ai-bot command responses
|
├── ai-comment-reply.yml # @codebot command responses
|
||||||
└── ai-chat.yml # Bartender chat
|
└── ai-chat.yml # Interactive AI chat
|
||||||
|
|
||||||
.gitea/workflows/ # Gitea Actions workflows
|
.gitea/workflows/ # Gitea Actions workflows
|
||||||
├── enterprise-ai-review.yml
|
├── enterprise-ai-review.yml
|
||||||
@@ -174,35 +139,36 @@ python main.py pr owner/repo 123
|
|||||||
# Triage an issue
|
# Triage an issue
|
||||||
python main.py issue owner/repo 456
|
python main.py issue owner/repo 456
|
||||||
|
|
||||||
# Respond to @ai-bot command
|
# Respond to @codebot command
|
||||||
python main.py comment owner/repo 456 "@ai-bot explain"
|
python main.py comment owner/repo 456 "@codebot explain"
|
||||||
|
|
||||||
# Analyze codebase
|
# Analyze codebase
|
||||||
python main.py codebase owner/repo
|
python main.py codebase owner/repo
|
||||||
|
|
||||||
# Chat with Bartender
|
# Chat with the AI bot
|
||||||
python main.py chat owner/repo "How does authentication work?"
|
python main.py chat owner/repo "How does authentication work?"
|
||||||
python main.py chat owner/repo "Find all API endpoints" --issue 789
|
python main.py chat owner/repo "Find all API endpoints" --issue 789
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## @ai-bot Commands
|
## @codebot Commands
|
||||||
|
|
||||||
In any issue comment:
|
In any issue comment:
|
||||||
|
|
||||||
| Command | Description |
|
| Command | Description |
|
||||||
|---------|-------------|
|
|---------|-------------|
|
||||||
| `@ai-bot summarize` | Summarize the issue in 2-3 sentences |
|
| `@codebot triage` | Full issue triage with auto-labeling and analysis |
|
||||||
| `@ai-bot explain` | Explain what the issue is about |
|
| `@codebot summarize` | Summarize the issue in 2-3 sentences |
|
||||||
| `@ai-bot suggest` | Suggest solutions or next steps |
|
| `@codebot explain` | Explain what the issue is about |
|
||||||
| `@ai-bot` (any question) | Chat with Bartender using codebase/web search |
|
| `@codebot suggest` | Suggest solutions or next steps |
|
||||||
|
| `@codebot` (any question) | Chat with AI using codebase/web search tools |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Bartender Chat
|
## Interactive Chat
|
||||||
|
|
||||||
Bartender is an interactive AI assistant with tool-calling capabilities:
|
The chat agent is an interactive AI assistant with tool-calling capabilities:
|
||||||
|
|
||||||
**Tools Available:**
|
**Tools Available:**
|
||||||
- `search_codebase` - Search repository files and code
|
- `search_codebase` - Search repository files and code
|
||||||
@@ -211,10 +177,10 @@ Bartender is an interactive AI assistant with tool-calling capabilities:
|
|||||||
|
|
||||||
**Example:**
|
**Example:**
|
||||||
```
|
```
|
||||||
@ai-bot How do I configure rate limiting in this project?
|
@codebot How do I configure rate limiting in this project?
|
||||||
```
|
```
|
||||||
|
|
||||||
Bartender will search the codebase, read relevant files, and provide a comprehensive answer.
|
The bot will search the codebase, read relevant files, and provide a comprehensive answer.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -242,12 +208,11 @@ agents:
|
|||||||
enabled: true
|
enabled: true
|
||||||
chat:
|
chat:
|
||||||
enabled: true
|
enabled: true
|
||||||
name: "Bartender"
|
|
||||||
searxng_url: "" # Or set SEARXNG_URL env var
|
searxng_url: "" # Or set SEARXNG_URL env var
|
||||||
|
|
||||||
interaction:
|
interaction:
|
||||||
respond_to_mentions: true
|
respond_to_mentions: true
|
||||||
mention_prefix: "@ai-bot" # Customize your bot name here!
|
mention_prefix: "@codebot" # Customize your bot name here!
|
||||||
commands:
|
commands:
|
||||||
- summarize
|
- summarize
|
||||||
- explain
|
- explain
|
||||||
@@ -258,34 +223,25 @@ interaction:
|
|||||||
|
|
||||||
## Customizing the Bot Name
|
## Customizing the Bot Name
|
||||||
|
|
||||||
You can change the bot's mention trigger from `@ai-bot` to any name you prefer:
|
The default bot name is `@codebot`. To change it:
|
||||||
|
|
||||||
**Step 1:** Edit `tools/ai-review/config.yml`:
|
**Step 1:** Edit `tools/ai-review/config.yml`:
|
||||||
```yaml
|
```yaml
|
||||||
interaction:
|
interaction:
|
||||||
mention_prefix: "@bartender" # or "@uni", "@joey", "@codebot", etc.
|
mention_prefix: "@yourname" # e.g., "@assistant", "@reviewer", etc.
|
||||||
```
|
```
|
||||||
|
|
||||||
**Step 2:** Update the workflow files to match:
|
**Step 2:** Update all workflow files in `.gitea/workflows/`:
|
||||||
|
- `ai-comment-reply.yml`
|
||||||
|
- `ai-chat.yml`
|
||||||
|
- `ai-issue-triage.yml`
|
||||||
|
|
||||||
For GitHub (`.github/workflows/ai-comment-reply.yml` and `ai-chat.yml`):
|
Look for and update:
|
||||||
```yaml
|
```yaml
|
||||||
if: contains(github.event.comment.body, '@bartender')
|
if: contains(github.event.comment.body, '@codebot')
|
||||||
```
|
```
|
||||||
|
|
||||||
For Gitea (`.gitea/workflows/ai-comment-reply.yml` and `ai-chat.yml`):
|
Change `@codebot` to your new bot name.
|
||||||
```yaml
|
|
||||||
if: contains(github.event.comment.body, '@bartender')
|
|
||||||
```
|
|
||||||
|
|
||||||
**Example bot names:**
|
|
||||||
| Name | Use Case |
|
|
||||||
|------|----------|
|
|
||||||
| `@bartender` | Friendly, conversational |
|
|
||||||
| `@uni` | Short, quick to type |
|
|
||||||
| `@joey` | Personal assistant feel |
|
|
||||||
| `@codebot` | Technical, code-focused |
|
|
||||||
| `@reviewer` | Review-focused |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -28,9 +28,9 @@ Handles issue triage, classification, and interaction.
|
|||||||
|
|
||||||
| Command | Description |
|
| Command | Description |
|
||||||
|---------|-------------|
|
|---------|-------------|
|
||||||
| `@ai-bot summarize` | Generate concise summary |
|
| `@codebot summarize` | Generate concise summary |
|
||||||
| `@ai-bot explain` | Detailed explanation |
|
| `@codebot explain` | Detailed explanation |
|
||||||
| `@ai-bot suggest` | Solution suggestions |
|
| `@codebot suggest` | Solution suggestions |
|
||||||
|
|
||||||
### Output
|
### Output
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@ Repository-wide quality and health analysis.
|
|||||||
|
|
||||||
- `schedule` - Cron schedule (default: weekly)
|
- `schedule` - Cron schedule (default: weekly)
|
||||||
- `workflow_dispatch` - Manual trigger
|
- `workflow_dispatch` - Manual trigger
|
||||||
- `@ai-bot codebase` - Comment command
|
- `@codebot codebase` - Comment command
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
@@ -184,13 +184,13 @@ Missing docstrings in 15 functions.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Chat Agent (Bartender)
|
## Chat Agent (Interactive Chat Agent)
|
||||||
|
|
||||||
Interactive AI chat assistant with tool-calling capabilities.
|
Interactive AI chat assistant with tool-calling capabilities.
|
||||||
|
|
||||||
### Triggers
|
### Triggers
|
||||||
|
|
||||||
- `issue_comment.created` - Any @ai-bot mention that isn't a specific command
|
- `issue_comment.created` - Any @codebot mention that isn't a specific command
|
||||||
- `chat` - Direct CLI invocation
|
- `chat` - Direct CLI invocation
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
@@ -219,7 +219,7 @@ The Chat Agent uses LLM function calling to gather information before responding
|
|||||||
agents:
|
agents:
|
||||||
chat:
|
chat:
|
||||||
enabled: true
|
enabled: true
|
||||||
name: "Bartender"
|
name: "CodeBot"
|
||||||
max_iterations: 5
|
max_iterations: 5
|
||||||
tools:
|
tools:
|
||||||
- search_codebase
|
- search_codebase
|
||||||
@@ -241,9 +241,9 @@ python main.py chat owner/repo "Explain this bug" --issue 123
|
|||||||
### Issue Comment Usage
|
### Issue Comment Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
@ai-bot How do I configure rate limiting?
|
@codebot How do I configure rate limiting?
|
||||||
@ai-bot Find all files that handle user authentication
|
@codebot Find all files that handle user authentication
|
||||||
@ai-bot What does the dispatcher module do?
|
@codebot What does the dispatcher module do?
|
||||||
```
|
```
|
||||||
|
|
||||||
### Output
|
### Output
|
||||||
|
|||||||
@@ -67,13 +67,13 @@ agents:
|
|||||||
schedule: "0 0 * * 0" # Cron schedule (weekly)
|
schedule: "0 0 * * 0" # Cron schedule (weekly)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Chat Agent (Bartender)
|
### Chat Agent (Interactive Chat Agent)
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
agents:
|
agents:
|
||||||
chat:
|
chat:
|
||||||
enabled: true
|
enabled: true
|
||||||
name: "Bartender" # Display name for the bot
|
name: "CodeBot" # Display name for the bot
|
||||||
max_iterations: 5 # Max tool calls per chat
|
max_iterations: 5 # Max tool calls per chat
|
||||||
tools:
|
tools:
|
||||||
- search_codebase # Search repository files
|
- search_codebase # Search repository files
|
||||||
@@ -103,7 +103,7 @@ interaction:
|
|||||||
```
|
```
|
||||||
|
|
||||||
**Example bot names:**
|
**Example bot names:**
|
||||||
- `@ai-bot` - Default, generic
|
- `@codebot` - Default, generic
|
||||||
- `@bartender` - Friendly, conversational
|
- `@bartender` - Friendly, conversational
|
||||||
- `@uni` - Short, quick to type
|
- `@uni` - Short, quick to type
|
||||||
- `@joey` - Personal assistant
|
- `@joey` - Personal assistant
|
||||||
@@ -112,7 +112,7 @@ interaction:
|
|||||||
```yaml
|
```yaml
|
||||||
interaction:
|
interaction:
|
||||||
respond_to_mentions: true
|
respond_to_mentions: true
|
||||||
mention_prefix: "@ai-bot"
|
mention_prefix: "@codebot"
|
||||||
commands:
|
commands:
|
||||||
- explain # Explain code/issue
|
- explain # Explain code/issue
|
||||||
- suggest # Suggest solutions
|
- suggest # Suggest solutions
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ mkdir -p .gitea/workflows
|
|||||||
| File | Trigger | Purpose |
|
| File | Trigger | Purpose |
|
||||||
|------|---------|---------|
|
|------|---------|---------|
|
||||||
| `enterprise-ai-review.yml` | PR opened/updated | Run AI code review |
|
| `enterprise-ai-review.yml` | PR opened/updated | Run AI code review |
|
||||||
| `ai-issue-review.yml` | Issue opened, @ai-bot | Triage issues & respond to commands |
|
| `ai-issue-review.yml` | Issue opened, @codebot | Triage issues & respond to commands |
|
||||||
| `ai-codebase-review.yml` | Weekly/manual | Analyze codebase health |
|
| `ai-codebase-review.yml` | Weekly/manual | Analyze codebase health |
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -89,8 +89,8 @@ Create these labels in your repository for auto-labeling:
|
|||||||
1. Create a new issue
|
1. Create a new issue
|
||||||
2. The AI should automatically triage and comment
|
2. The AI should automatically triage and comment
|
||||||
|
|
||||||
### Test @ai-bot Commands:
|
### Test @codebot Commands:
|
||||||
1. On any issue, comment: `@ai-bot summarize`
|
1. On any issue, comment: `@codebot summarize`
|
||||||
2. The AI should respond with a summary
|
2. The AI should respond with a summary
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -126,8 +126,8 @@ python main.py pr owner/repo 123
|
|||||||
# Triage a new issue
|
# Triage a new issue
|
||||||
python main.py issue owner/repo 456
|
python main.py issue owner/repo 456
|
||||||
|
|
||||||
# Handle @ai-bot command in comment
|
# Handle @codebot command in comment
|
||||||
python main.py comment owner/repo 456 "@ai-bot summarize"
|
python main.py comment owner/repo 456 "@codebot summarize"
|
||||||
|
|
||||||
# Analyze codebase
|
# Analyze codebase
|
||||||
python main.py codebase owner/repo
|
python main.py codebase owner/repo
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ env:
|
|||||||
2. Verify token has `issue:write` permission
|
2. Verify token has `issue:write` permission
|
||||||
3. Check workflow logs for API errors
|
3. Check workflow logs for API errors
|
||||||
|
|
||||||
### @ai-bot edits the issue instead of replying
|
### @codebot edits the issue instead of replying
|
||||||
|
|
||||||
**Causes:**
|
**Causes:**
|
||||||
- Workflow is using the wrong CLI command for comments
|
- Workflow is using the wrong CLI command for comments
|
||||||
@@ -149,7 +149,7 @@ env:
|
|||||||
**Solutions:**
|
**Solutions:**
|
||||||
1. Ensure your workflow uses the `comment` command for mentions:
|
1. Ensure your workflow uses the `comment` command for mentions:
|
||||||
```yaml
|
```yaml
|
||||||
python main.py comment owner/repo 123 "@ai-bot ..."
|
python main.py comment owner/repo 123 "@codebot ..."
|
||||||
```
|
```
|
||||||
2. Verify you have separate jobs for `issues` vs `issue_comment` events (see [Workflows](workflows.md))
|
2. Verify you have separate jobs for `issues` vs `issue_comment` events (see [Workflows](workflows.md))
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,23 @@
|
|||||||
# Workflows
|
# Workflows
|
||||||
|
|
||||||
This document provides ready-to-use workflow files for integrating AI code review into your repositories. Workflows are provided for both **GitHub Actions** and **Gitea Actions**.
|
This document provides ready-to-use workflow files for integrating AI code review into your Gitea repositories.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Platform Comparison
|
## Gitea Workflows Overview
|
||||||
|
|
||||||
| Feature | GitHub | Gitea |
|
| Feature | Configuration |
|
||||||
|---------|--------|-------|
|
|---------|--------------|
|
||||||
| Context variable | `github.*` | `gitea.*` |
|
| Context variable | `gitea.*` |
|
||||||
| Default token | `GITHUB_TOKEN` | `AI_REVIEW_TOKEN` (custom) |
|
| Token | `AI_REVIEW_TOKEN` (custom secret) |
|
||||||
| API URL | `https://api.github.com` | Your Gitea instance URL |
|
| API URL | Your Gitea instance URL (e.g., `https://git.example.com/api/v1`) |
|
||||||
| Tools location | Same repo (`tools/ai-review`) | Checkout from central repo |
|
| Tools location | Checkout from central OpenRabbit repo |
|
||||||
|
|
||||||
|
All workflows are located in `.gitea/workflows/` directory.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## GitHub Workflows
|
## Gitea Workflows
|
||||||
|
|
||||||
### PR Review Workflow
|
### PR Review Workflow
|
||||||
|
|
||||||
@@ -99,7 +101,7 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
ai-reply:
|
ai-reply:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: contains(github.event.comment.body, '@ai-bot')
|
if: contains(github.event.comment.body, '@codebot')
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
@@ -256,7 +258,7 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
ai-reply:
|
ai-reply:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: contains(github.event.comment.body, '@ai-bot')
|
if: contains(github.event.comment.body, '@codebot')
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
@@ -377,13 +379,13 @@ AI_REVIEW_API_URL: https://your-gitea.example.com/api/v1
|
|||||||
|
|
||||||
## Chat/Bartender Workflow
|
## Chat/Bartender Workflow
|
||||||
|
|
||||||
Both platforms support the Bartender chat agent through the comment reply workflow. When `@ai-bot` is mentioned with a question (not a specific command like `summarize`), the Chat Agent handles it with tool calling capabilities.
|
Both platforms support the Bartender chat agent through the comment reply workflow. When `@codebot` is mentioned with a question (not a specific command like `summarize`), the Chat Agent handles it with tool calling capabilities.
|
||||||
|
|
||||||
To enable web search, set the `SEARXNG_URL` secret to your SearXNG instance URL.
|
To enable web search, set the `SEARXNG_URL` secret to your SearXNG instance URL.
|
||||||
|
|
||||||
**Example usage:**
|
**Example usage:**
|
||||||
```
|
```
|
||||||
@ai-bot How do I configure rate limiting?
|
@codebot How do I configure rate limiting?
|
||||||
@ai-bot Find all authentication-related files
|
@codebot Find all authentication-related files
|
||||||
@ai-bot What does the dispatcher module do?
|
@codebot What does the dispatcher module do?
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -96,7 +96,9 @@ class CodebaseAgent(BaseAgent):
|
|||||||
|
|
||||||
def execute(self, context: AgentContext) -> AgentResult:
|
def execute(self, context: AgentContext) -> AgentResult:
|
||||||
"""Execute codebase analysis."""
|
"""Execute codebase analysis."""
|
||||||
self.logger.info(f"Starting codebase analysis for {context.owner}/{context.repo}")
|
self.logger.info(
|
||||||
|
f"Starting codebase analysis for {context.owner}/{context.repo}"
|
||||||
|
)
|
||||||
|
|
||||||
actions_taken = []
|
actions_taken = []
|
||||||
|
|
||||||
@@ -192,7 +194,7 @@ class CodebaseAgent(BaseAgent):
|
|||||||
|
|
||||||
# Check for docstrings (Python)
|
# Check for docstrings (Python)
|
||||||
if ext == ".py":
|
if ext == ".py":
|
||||||
if 'def ' in content and '"""' not in content:
|
if "def " in content and '"""' not in content:
|
||||||
metrics.missing_docstrings += 1
|
metrics.missing_docstrings += 1
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -273,23 +275,45 @@ Be constructive and actionable. Focus on the most impactful improvements.
|
|||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"AI analysis failed: {e}")
|
self.logger.error(f"AI analysis failed: {e}")
|
||||||
# Try to log the raw response if possible (requires accessing the last response)
|
self.logger.debug(f"Full error details: {type(e).__name__}: {str(e)}")
|
||||||
# Since we don't have direct access here, we rely on having good logging in LLMClient if needed.
|
|
||||||
# But let's add a note to the summary.
|
|
||||||
# Calculate basic health score from metrics
|
# Calculate basic health score from metrics
|
||||||
health_score = 70
|
health_score = 70
|
||||||
if metrics.todo_count > 10:
|
if metrics.todo_count > 10:
|
||||||
health_score -= 10
|
health_score -= 10
|
||||||
if metrics.fixme_count > 5:
|
if metrics.fixme_count > 5:
|
||||||
health_score -= 10
|
health_score -= 10
|
||||||
|
if metrics.deprecated_count > 3:
|
||||||
|
health_score -= 5
|
||||||
|
|
||||||
|
# Build recommendations based on metrics
|
||||||
|
recommendations = []
|
||||||
|
if metrics.todo_count > 5:
|
||||||
|
recommendations.append(
|
||||||
|
f"Review and address {metrics.todo_count} TODO comments"
|
||||||
|
)
|
||||||
|
if metrics.fixme_count > 0:
|
||||||
|
recommendations.append(
|
||||||
|
f"Review and fix {metrics.fixme_count} FIXME markers"
|
||||||
|
)
|
||||||
|
if metrics.deprecated_count > 0:
|
||||||
|
recommendations.append(
|
||||||
|
f"Update {metrics.deprecated_count} deprecated code sections"
|
||||||
|
)
|
||||||
|
if metrics.missing_docstrings > 5:
|
||||||
|
recommendations.append("Consider adding more documentation")
|
||||||
|
if not recommendations:
|
||||||
|
recommendations.append("Codebase appears well-maintained")
|
||||||
|
|
||||||
return CodebaseReport(
|
return CodebaseReport(
|
||||||
summary=f"Basic analysis complete (AI unavailable: {e})",
|
summary=f"Basic metrics analysis complete. {metrics.total_files} files analyzed across {len(metrics.languages)} languages.",
|
||||||
health_score=health_score,
|
health_score=health_score,
|
||||||
metrics=metrics,
|
metrics=metrics,
|
||||||
issues=[],
|
issues=[],
|
||||||
recommendations=["Manual review recommended"],
|
recommendations=recommendations,
|
||||||
architecture_notes=[],
|
architecture_notes=[
|
||||||
|
f"Primary languages: {', '.join(list(metrics.languages.keys())[:3])}"
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
def _get_key_files_content(
|
def _get_key_files_content(
|
||||||
@@ -386,7 +410,11 @@ Be constructive and actionable. Focus on the most impactful improvements.
|
|||||||
|
|
||||||
def _generate_report_body(self, report: CodebaseReport) -> str:
|
def _generate_report_body(self, report: CodebaseReport) -> str:
|
||||||
"""Generate the report issue body."""
|
"""Generate the report issue body."""
|
||||||
health_emoji = "🟢" if report.health_score >= 80 else ("🟡" if report.health_score >= 60 else "🔴")
|
health_emoji = (
|
||||||
|
"🟢"
|
||||||
|
if report.health_score >= 80
|
||||||
|
else ("🟡" if report.health_score >= 60 else "🔴")
|
||||||
|
)
|
||||||
|
|
||||||
lines = [
|
lines = [
|
||||||
f"{self.AI_DISCLAIMER}",
|
f"{self.AI_DISCLAIMER}",
|
||||||
@@ -427,7 +455,11 @@ Be constructive and actionable. Focus on the most impactful improvements.
|
|||||||
lines.append("")
|
lines.append("")
|
||||||
for issue in report.issues[:10]:
|
for issue in report.issues[:10]:
|
||||||
severity = issue.get("severity", "MEDIUM")
|
severity = issue.get("severity", "MEDIUM")
|
||||||
emoji = "🔴" if severity == "HIGH" else ("🟡" if severity == "MEDIUM" else "🟢")
|
emoji = (
|
||||||
|
"🔴"
|
||||||
|
if severity == "HIGH"
|
||||||
|
else ("🟡" if severity == "MEDIUM" else "🟢")
|
||||||
|
)
|
||||||
lines.append(f"### [{severity}] {issue.get('category', 'General')}")
|
lines.append(f"### [{severity}] {issue.get('category', 'General')}")
|
||||||
lines.append("")
|
lines.append("")
|
||||||
lines.append(issue.get("description", ""))
|
lines.append(issue.get("description", ""))
|
||||||
|
|||||||
@@ -262,9 +262,7 @@ class IssueAgent(BaseAgent):
|
|||||||
if labels_to_add:
|
if labels_to_add:
|
||||||
try:
|
try:
|
||||||
self.gitea.add_issue_labels(owner, repo, issue_index, labels_to_add)
|
self.gitea.add_issue_labels(owner, repo, issue_index, labels_to_add)
|
||||||
return [
|
return [name for name, id in label_map.items() if id in labels_to_add]
|
||||||
name for name, id in label_map.items() if id in labels_to_add
|
|
||||||
]
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"Failed to add labels: {e}")
|
self.logger.warning(f"Failed to add labels: {e}")
|
||||||
|
|
||||||
@@ -336,6 +334,8 @@ class IssueAgent(BaseAgent):
|
|||||||
return self._command_explain(title, body)
|
return self._command_explain(title, body)
|
||||||
elif command == "suggest":
|
elif command == "suggest":
|
||||||
return self._command_suggest(title, body)
|
return self._command_suggest(title, body)
|
||||||
|
elif command == "triage":
|
||||||
|
return self._command_triage(context, issue)
|
||||||
|
|
||||||
return f"{self.AI_DISCLAIMER}\n\nSorry, I don't understand the command `{command}`."
|
return f"{self.AI_DISCLAIMER}\n\nSorry, I don't understand the command `{command}`."
|
||||||
|
|
||||||
@@ -390,3 +390,33 @@ Be practical and concise."""
|
|||||||
return f"{self.AI_DISCLAIMER}\n\n**Suggestions:**\n{response.content}"
|
return f"{self.AI_DISCLAIMER}\n\n**Suggestions:**\n{response.content}"
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return f"{self.AI_DISCLAIMER}\n\nSorry, I was unable to generate suggestions. Error: {e}"
|
return f"{self.AI_DISCLAIMER}\n\nSorry, I was unable to generate suggestions. Error: {e}"
|
||||||
|
|
||||||
|
def _command_triage(self, context: AgentContext, issue: dict) -> str:
|
||||||
|
"""Perform full triage analysis on the issue."""
|
||||||
|
title = issue.get("title", "")
|
||||||
|
body = issue.get("body", "")
|
||||||
|
author = issue.get("user", {}).get("login", "unknown")
|
||||||
|
existing_labels = [l.get("name", "") for l in issue.get("labels", [])]
|
||||||
|
issue_index = issue.get("number")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Perform triage analysis
|
||||||
|
triage = self._triage_issue(title, body, author, existing_labels)
|
||||||
|
|
||||||
|
# Apply labels if enabled
|
||||||
|
agent_config = self.config.get("agents", {}).get("issue", {})
|
||||||
|
labels_applied = []
|
||||||
|
if agent_config.get("auto_label", True):
|
||||||
|
labels_applied = self._apply_labels(
|
||||||
|
context.owner, context.repo, issue_index, triage
|
||||||
|
)
|
||||||
|
|
||||||
|
# Generate response
|
||||||
|
response = self._generate_triage_comment(triage, issue)
|
||||||
|
|
||||||
|
if labels_applied:
|
||||||
|
response += f"\n\n**Labels Applied:** {', '.join(labels_applied)}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
except Exception as e:
|
||||||
|
return f"{self.AI_DISCLAIMER}\n\nSorry, I was unable to triage this issue. Error: {e}"
|
||||||
|
|||||||
@@ -346,7 +346,9 @@ class LLMClient:
|
|||||||
config: Provider-specific configuration.
|
config: Provider-specific configuration.
|
||||||
"""
|
"""
|
||||||
if provider not in self.PROVIDERS:
|
if provider not in self.PROVIDERS:
|
||||||
raise ValueError(f"Unknown provider: {provider}. Available: {list(self.PROVIDERS.keys())}")
|
raise ValueError(
|
||||||
|
f"Unknown provider: {provider}. Available: {list(self.PROVIDERS.keys())}"
|
||||||
|
)
|
||||||
|
|
||||||
self.provider_name = provider
|
self.provider_name = provider
|
||||||
self.config = config or {}
|
self.config = config or {}
|
||||||
@@ -405,6 +407,8 @@ class LLMClient:
|
|||||||
|
|
||||||
Handles markdown code blocks and preamble text.
|
Handles markdown code blocks and preamble text.
|
||||||
"""
|
"""
|
||||||
|
import re
|
||||||
|
|
||||||
content = content.strip()
|
content = content.strip()
|
||||||
|
|
||||||
# Attempt 1: direct parse
|
# Attempt 1: direct parse
|
||||||
@@ -413,16 +417,24 @@ class LLMClient:
|
|||||||
except json.JSONDecodeError:
|
except json.JSONDecodeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Attempt 2: Extract from markdown code blocks
|
# Attempt 2: Extract from markdown code blocks (improved regex)
|
||||||
if "```" in content:
|
if "```" in content:
|
||||||
# Find the JSON block
|
# Try multiple code block patterns
|
||||||
import re
|
patterns = [
|
||||||
match = re.search(r"```(?:json)?\s*([\s\S]*?)\s*```", content)
|
r"```json\s*\n([\s\S]*?)\n```", # ```json with newlines
|
||||||
if match:
|
r"```json\s*([\s\S]*?)```", # ```json without newlines
|
||||||
try:
|
r"```\s*\n([\s\S]*?)\n```", # ``` with newlines
|
||||||
return json.loads(match.group(1))
|
r"```\s*([\s\S]*?)```", # ``` without newlines
|
||||||
except json.JSONDecodeError:
|
]
|
||||||
pass
|
|
||||||
|
for pattern in patterns:
|
||||||
|
match = re.search(pattern, content)
|
||||||
|
if match:
|
||||||
|
try:
|
||||||
|
json_str = match.group(1).strip()
|
||||||
|
return json.loads(json_str)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
continue
|
||||||
|
|
||||||
# Attempt 3: Find first { and last }
|
# Attempt 3: Find first { and last }
|
||||||
try:
|
try:
|
||||||
@@ -435,17 +447,22 @@ class LLMClient:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
# Attempt 4: Fix common JSON errors (comments, trailing commas)
|
# Attempt 4: Fix common JSON errors (comments, trailing commas)
|
||||||
# This is risky but helpful for LLM output
|
|
||||||
try:
|
try:
|
||||||
# Remove comments
|
# Remove comments
|
||||||
import re
|
|
||||||
json_str = re.sub(r"//.*", "", content)
|
json_str = re.sub(r"//.*", "", content)
|
||||||
json_str = re.sub(r"/\*[\s\S]*?\*/", "", json_str)
|
json_str = re.sub(r"/\*[\s\S]*?\*/", "", json_str)
|
||||||
return json.loads(json_str)
|
# Try to extract JSON after cleaning
|
||||||
except json.JSONDecodeError as e:
|
start = json_str.find("{")
|
||||||
# If all attempts fail, raise an error with the content for debugging
|
end = json_str.rfind("}")
|
||||||
snippet = content[:500] + "..." if len(content) > 500 else content
|
if start != -1 and end != -1:
|
||||||
raise ValueError(f"Failed to parse JSON response: {e}. Raw content snippet: {snippet!r}")
|
json_str = json_str[start : end + 1]
|
||||||
|
return json.loads(json_str)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# If all attempts fail, raise an error with the content for debugging
|
||||||
|
snippet = content[:500] + "..." if len(content) > 500 else content
|
||||||
|
raise ValueError(f"Failed to parse JSON response: {snippet!r}")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_config(cls, config: dict) -> "LLMClient":
|
def from_config(cls, config: dict) -> "LLMClient":
|
||||||
@@ -469,7 +486,9 @@ class LLMClient:
|
|||||||
}
|
}
|
||||||
elif provider == "openrouter":
|
elif provider == "openrouter":
|
||||||
provider_config = {
|
provider_config = {
|
||||||
"model": config.get("model", {}).get("openrouter", "anthropic/claude-3.5-sonnet"),
|
"model": config.get("model", {}).get(
|
||||||
|
"openrouter", "anthropic/claude-3.5-sonnet"
|
||||||
|
),
|
||||||
"temperature": config.get("temperature", 0),
|
"temperature": config.get("temperature", 0),
|
||||||
"max_tokens": config.get("max_tokens", 16000),
|
"max_tokens": config.get("max_tokens", 16000),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,49 +1,49 @@
|
|||||||
provider: openai # openai | openrouter | ollama
|
provider: openai # openai | openrouter | ollama
|
||||||
|
|
||||||
model:
|
model:
|
||||||
openai: gpt-4.1-mini
|
openai: gpt-4.1-mini
|
||||||
openrouter: anthropic/claude-3.5-sonnet
|
openrouter: anthropic/claude-3.5-sonnet
|
||||||
ollama: codellama:13b
|
ollama: codellama:13b
|
||||||
|
|
||||||
temperature: 0
|
temperature: 0
|
||||||
max_tokens: 4096
|
max_tokens: 4096
|
||||||
|
|
||||||
# Review settings
|
# Review settings
|
||||||
review:
|
review:
|
||||||
fail_on_severity: HIGH
|
fail_on_severity: HIGH
|
||||||
max_diff_lines: 800
|
max_diff_lines: 800
|
||||||
inline_comments: true
|
inline_comments: true
|
||||||
security_scan: true
|
security_scan: true
|
||||||
|
|
||||||
# Agent settings
|
# Agent settings
|
||||||
agents:
|
agents:
|
||||||
issue:
|
issue:
|
||||||
enabled: true
|
enabled: true
|
||||||
auto_label: true
|
auto_label: true
|
||||||
auto_triage: true
|
auto_triage: true
|
||||||
duplicate_threshold: 0.85
|
duplicate_threshold: 0.85
|
||||||
events:
|
events:
|
||||||
- opened
|
- opened
|
||||||
- labeled
|
- labeled
|
||||||
pr:
|
pr:
|
||||||
enabled: true
|
enabled: true
|
||||||
inline_comments: true
|
inline_comments: true
|
||||||
security_scan: true
|
security_scan: true
|
||||||
events:
|
events:
|
||||||
- opened
|
- opened
|
||||||
- synchronize
|
- synchronize
|
||||||
codebase:
|
codebase:
|
||||||
enabled: true
|
enabled: true
|
||||||
schedule: "0 0 * * 0" # Weekly on Sunday
|
schedule: "0 0 * * 0" # Weekly on Sunday
|
||||||
chat:
|
chat:
|
||||||
enabled: true
|
enabled: true
|
||||||
name: "Bartender"
|
name: "Bartender"
|
||||||
max_iterations: 5 # Max tool call iterations per chat
|
max_iterations: 5 # Max tool call iterations per chat
|
||||||
tools:
|
tools:
|
||||||
- search_codebase
|
- search_codebase
|
||||||
- read_file
|
- read_file
|
||||||
- search_web
|
- search_web
|
||||||
searxng_url: "" # Set via SEARXNG_URL env var or here
|
searxng_url: "" # Set via SEARXNG_URL env var or here
|
||||||
|
|
||||||
# Interaction settings
|
# Interaction settings
|
||||||
# CUSTOMIZE YOUR BOT NAME HERE!
|
# CUSTOMIZE YOUR BOT NAME HERE!
|
||||||
@@ -56,41 +56,42 @@ agents:
|
|||||||
# NOTE: Also update the workflow files (.github/workflows/ or .gitea/workflows/)
|
# NOTE: Also update the workflow files (.github/workflows/ or .gitea/workflows/)
|
||||||
# to match this prefix in the 'if: contains(...)' condition
|
# to match this prefix in the 'if: contains(...)' condition
|
||||||
interaction:
|
interaction:
|
||||||
respond_to_mentions: true
|
respond_to_mentions: true
|
||||||
mention_prefix: "@bartender" # Change this to customize your bot's name!
|
mention_prefix: "@codebot" # Change this to customize your bot's name!
|
||||||
commands:
|
commands:
|
||||||
- explain
|
- explain
|
||||||
- suggest
|
- suggest
|
||||||
- security
|
- security
|
||||||
- summarize
|
- summarize
|
||||||
|
- triage
|
||||||
|
|
||||||
# Enterprise settings
|
# Enterprise settings
|
||||||
enterprise:
|
enterprise:
|
||||||
audit_log: true
|
audit_log: true
|
||||||
audit_path: "/var/log/ai-review/"
|
audit_path: "/var/log/ai-review/"
|
||||||
metrics_enabled: true
|
metrics_enabled: true
|
||||||
rate_limit:
|
rate_limit:
|
||||||
requests_per_minute: 30
|
requests_per_minute: 30
|
||||||
max_concurrent: 4
|
max_concurrent: 4
|
||||||
|
|
||||||
# Label mappings for auto-labeling
|
# Label mappings for auto-labeling
|
||||||
labels:
|
labels:
|
||||||
priority:
|
priority:
|
||||||
high: "priority: high"
|
high: "priority: high"
|
||||||
medium: "priority: medium"
|
medium: "priority: medium"
|
||||||
low: "priority: low"
|
low: "priority: low"
|
||||||
type:
|
type:
|
||||||
bug: "type: bug"
|
bug: "type: bug"
|
||||||
feature: "type: feature"
|
feature: "type: feature"
|
||||||
question: "type: question"
|
question: "type: question"
|
||||||
docs: "type: documentation"
|
docs: "type: documentation"
|
||||||
status:
|
status:
|
||||||
ai_approved: "ai-approved"
|
ai_approved: "ai-approved"
|
||||||
ai_changes_required: "ai-changes-required"
|
ai_changes_required: "ai-changes-required"
|
||||||
ai_reviewed: "ai-reviewed"
|
ai_reviewed: "ai-reviewed"
|
||||||
|
|
||||||
# Security scanning rules
|
# Security scanning rules
|
||||||
security:
|
security:
|
||||||
enabled: true
|
enabled: true
|
||||||
fail_on_high: true
|
fail_on_high: true
|
||||||
rules_file: "security/security_rules.yml"
|
rules_file: "security/security_rules.yml"
|
||||||
|
|||||||
Reference in New Issue
Block a user