From 69d9963597479bcf64ac6083a70556aee04ba42d Mon Sep 17 00:00:00 2001 From: latte Date: Sun, 28 Dec 2025 14:10:04 +0000 Subject: [PATCH] update --- .gitea/workflows/ai-issue-triage.yml | 55 ++-- .github/workflows/ai-chat.yml | 36 --- .github/workflows/ai-codebase-review.yml | 51 ---- .github/workflows/ai-comment-reply.yml | 36 --- .github/workflows/ai-issue-triage.yml | 30 -- .github/workflows/ai-review.yml | 52 ---- CLAUDE.md | 347 +++++++++++++++++++++++ README.md | 118 +++----- docs/agents.md | 20 +- docs/configuration.md | 8 +- docs/getting-started.md | 10 +- docs/troubleshooting.md | 4 +- docs/workflows.md | 32 ++- tools/ai-review/agents/codebase_agent.py | 52 +++- tools/ai-review/agents/issue_agent.py | 36 ++- tools/ai-review/clients/llm_client.py | 55 ++-- tools/ai-review/config.yml | 129 ++++----- 17 files changed, 627 insertions(+), 444 deletions(-) delete mode 100644 .github/workflows/ai-chat.yml delete mode 100644 .github/workflows/ai-codebase-review.yml delete mode 100644 .github/workflows/ai-comment-reply.yml delete mode 100644 .github/workflows/ai-issue-triage.yml delete mode 100644 .github/workflows/ai-review.yml create mode 100644 CLAUDE.md diff --git a/.gitea/workflows/ai-issue-triage.yml b/.gitea/workflows/ai-issue-triage.yml index 1cb54b3..b3a3289 100644 --- a/.gitea/workflows/ai-issue-triage.yml +++ b/.gitea/workflows/ai-issue-triage.yml @@ -1,36 +1,37 @@ name: AI Issue Triage on: - issues: - types: [opened, labeled] + issue_comment: + types: [created] jobs: - ai-triage: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 + ai-triage: + runs-on: ubuntu-latest + # Only run if comment contains @codebot triage + if: contains(github.event.comment.body, '@codebot triage') + steps: + - uses: actions/checkout@v4 - - uses: actions/checkout@v4 - with: - repository: Hiddenden/openrabbit - path: .ai-review - token: ${{ secrets.AI_REVIEW_TOKEN }} + - uses: actions/checkout@v4 + with: + repository: Hiddenden/openrabbit + path: .ai-review + token: ${{ secrets.AI_REVIEW_TOKEN }} - - uses: actions/setup-python@v5 - with: - python-version: "3.11" + - uses: actions/setup-python@v5 + with: + python-version: "3.11" - - run: pip install requests pyyaml + - run: pip install requests pyyaml - - name: Run AI Issue Triage - env: - AI_REVIEW_TOKEN: ${{ secrets.AI_REVIEW_TOKEN }} - AI_REVIEW_REPO: ${{ gitea.repository }} - AI_REVIEW_API_URL: https://git.hiddenden.cafe/api/v1 - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} - OLLAMA_HOST: ${{ secrets.OLLAMA_HOST }} - run: | - cd .ai-review/tools/ai-review - python main.py issue ${{ gitea.repository }} ${{ gitea.event.issue.number }} \ - --title "${{ gitea.event.issue.title }}" + - name: Run AI Issue Triage + env: + AI_REVIEW_TOKEN: ${{ secrets.AI_REVIEW_TOKEN }} + AI_REVIEW_REPO: ${{ gitea.repository }} + AI_REVIEW_API_URL: https://git.hiddenden.cafe/api/v1 + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} + OLLAMA_HOST: ${{ secrets.OLLAMA_HOST }} + run: | + cd .ai-review/tools/ai-review + python main.py issue ${{ gitea.repository }} ${{ gitea.event.issue.number }} diff --git a/.github/workflows/ai-chat.yml b/.github/workflows/ai-chat.yml deleted file mode 100644 index 76d2554..0000000 --- a/.github/workflows/ai-chat.yml +++ /dev/null @@ -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 }}" diff --git a/.github/workflows/ai-codebase-review.yml b/.github/workflows/ai-codebase-review.yml deleted file mode 100644 index f384059..0000000 --- a/.github/workflows/ai-codebase-review.yml +++ /dev/null @@ -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 }} diff --git a/.github/workflows/ai-comment-reply.yml b/.github/workflows/ai-comment-reply.yml deleted file mode 100644 index 9bba89b..0000000 --- a/.github/workflows/ai-comment-reply.yml +++ /dev/null @@ -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 }}" diff --git a/.github/workflows/ai-issue-triage.yml b/.github/workflows/ai-issue-triage.yml deleted file mode 100644 index 3c4a2dd..0000000 --- a/.github/workflows/ai-issue-triage.yml +++ /dev/null @@ -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 }}" diff --git a/.github/workflows/ai-review.yml b/.github/workflows/ai-review.yml deleted file mode 100644 index d637c16..0000000 --- a/.github/workflows/ai-review.yml +++ /dev/null @@ -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 diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..918d239 --- /dev/null +++ b/CLAUDE.md @@ -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 ` + +## 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. diff --git a/README.md b/README.md index 73e6193..e5a0b56 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 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 | |---------|-------------| | **PR Review** | Inline comments, security scanning, severity-based CI failure | -| **Issue Triage** | Auto-classification, labeling, priority assignment | -| **Chat (Bartender)** | Interactive AI chat with codebase search and web search tools | -| **@ai-bot Commands** | `@ai-bot summarize`, `explain`, `suggest` in issue comments | +| **Issue Triage** | On-demand classification, labeling, priority assignment via `@codebot triage` | +| **Chat** | Interactive AI chat with codebase search and web search tools | +| **@codebot Commands** | `@codebot summarize`, `explain`, `suggest`, `triage` in issue comments | | **Codebase Analysis** | Health scores, tech debt tracking, weekly reports | | **Security Scanner** | 17 OWASP-aligned rules for vulnerability detection | | **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 -Workflows are provided for both platforms: - -| 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 }} -``` +Workflows are located in `.gitea/workflows/`. #### Gitea Example +#### Gitea PR Review Workflow + ```yaml -# .gitea/workflows/ai-review.yml +# .gitea/workflows/enterprise-ai-review.yml name: AI PR Review on: [pull_request] @@ -115,7 +80,7 @@ jobs: 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 @@ -132,10 +97,10 @@ Create these labels in your repository for auto-labeling: tools/ai-review/ ├── agents/ # Agent implementations │ ├── 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 │ ├── 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 │ ├── gitea_client.py # Gitea REST API wrapper │ └── llm_client.py # Multi-provider LLM client with tool support @@ -152,8 +117,8 @@ tools/ai-review/ ├── ai-review.yml # PR review workflow ├── ai-issue-triage.yml # Issue triage workflow ├── ai-codebase-review.yml # Codebase analysis -├── ai-comment-reply.yml # @ai-bot command responses -└── ai-chat.yml # Bartender chat +├── ai-comment-reply.yml # @codebot command responses +└── ai-chat.yml # Interactive AI chat .gitea/workflows/ # Gitea Actions workflows ├── enterprise-ai-review.yml @@ -174,35 +139,36 @@ python main.py pr owner/repo 123 # Triage an issue python main.py issue owner/repo 456 -# Respond to @ai-bot command -python main.py comment owner/repo 456 "@ai-bot explain" +# Respond to @codebot command +python main.py comment owner/repo 456 "@codebot explain" # Analyze codebase 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 "Find all API endpoints" --issue 789 ``` --- -## @ai-bot Commands +## @codebot Commands In any issue comment: | Command | Description | |---------|-------------| -| `@ai-bot summarize` | Summarize the issue in 2-3 sentences | -| `@ai-bot explain` | Explain what the issue is about | -| `@ai-bot suggest` | Suggest solutions or next steps | -| `@ai-bot` (any question) | Chat with Bartender using codebase/web search | +| `@codebot triage` | Full issue triage with auto-labeling and analysis | +| `@codebot summarize` | Summarize the issue in 2-3 sentences | +| `@codebot explain` | Explain what the issue is about | +| `@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:** - `search_codebase` - Search repository files and code @@ -211,10 +177,10 @@ Bartender is an interactive AI assistant with tool-calling capabilities: **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 chat: enabled: true - name: "Bartender" searxng_url: "" # Or set SEARXNG_URL env var interaction: respond_to_mentions: true - mention_prefix: "@ai-bot" # Customize your bot name here! + mention_prefix: "@codebot" # Customize your bot name here! commands: - summarize - explain @@ -258,34 +223,25 @@ interaction: ## 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`: ```yaml 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 -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`): -```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 | +Change `@codebot` to your new bot name. --- diff --git a/docs/agents.md b/docs/agents.md index 8df0dc0..71ff94e 100644 --- a/docs/agents.md +++ b/docs/agents.md @@ -28,9 +28,9 @@ Handles issue triage, classification, and interaction. | Command | Description | |---------|-------------| -| `@ai-bot summarize` | Generate concise summary | -| `@ai-bot explain` | Detailed explanation | -| `@ai-bot suggest` | Solution suggestions | +| `@codebot summarize` | Generate concise summary | +| `@codebot explain` | Detailed explanation | +| `@codebot suggest` | Solution suggestions | ### Output @@ -127,7 +127,7 @@ Repository-wide quality and health analysis. - `schedule` - Cron schedule (default: weekly) - `workflow_dispatch` - Manual trigger -- `@ai-bot codebase` - Comment command +- `@codebot codebase` - Comment command ### 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. ### 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 ### Features @@ -219,7 +219,7 @@ The Chat Agent uses LLM function calling to gather information before responding agents: chat: enabled: true - name: "Bartender" + name: "CodeBot" max_iterations: 5 tools: - search_codebase @@ -241,9 +241,9 @@ python main.py chat owner/repo "Explain this bug" --issue 123 ### Issue Comment Usage ``` -@ai-bot How do I configure rate limiting? -@ai-bot Find all files that handle user authentication -@ai-bot What does the dispatcher module do? +@codebot How do I configure rate limiting? +@codebot Find all files that handle user authentication +@codebot What does the dispatcher module do? ``` ### Output diff --git a/docs/configuration.md b/docs/configuration.md index 8d4fbcd..e555927 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -67,13 +67,13 @@ agents: schedule: "0 0 * * 0" # Cron schedule (weekly) ``` -### Chat Agent (Bartender) +### Chat Agent (Interactive Chat Agent) ```yaml agents: chat: enabled: true - name: "Bartender" # Display name for the bot + name: "CodeBot" # Display name for the bot max_iterations: 5 # Max tool calls per chat tools: - search_codebase # Search repository files @@ -103,7 +103,7 @@ interaction: ``` **Example bot names:** -- `@ai-bot` - Default, generic +- `@codebot` - Default, generic - `@bartender` - Friendly, conversational - `@uni` - Short, quick to type - `@joey` - Personal assistant @@ -112,7 +112,7 @@ interaction: ```yaml interaction: respond_to_mentions: true - mention_prefix: "@ai-bot" + mention_prefix: "@codebot" commands: - explain # Explain code/issue - suggest # Suggest solutions diff --git a/docs/getting-started.md b/docs/getting-started.md index 0899c6a..4c1a1da 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -51,7 +51,7 @@ mkdir -p .gitea/workflows | File | Trigger | Purpose | |------|---------|---------| | `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 | --- @@ -89,8 +89,8 @@ Create these labels in your repository for auto-labeling: 1. Create a new issue 2. The AI should automatically triage and comment -### Test @ai-bot Commands: -1. On any issue, comment: `@ai-bot summarize` +### Test @codebot Commands: +1. On any issue, comment: `@codebot summarize` 2. The AI should respond with a summary --- @@ -126,8 +126,8 @@ python main.py pr owner/repo 123 # Triage a new issue python main.py issue owner/repo 456 -# Handle @ai-bot command in comment -python main.py comment owner/repo 456 "@ai-bot summarize" +# Handle @codebot command in comment +python main.py comment owner/repo 456 "@codebot summarize" # Analyze codebase python main.py codebase owner/repo diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 7029e73..d15bc6d 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -140,7 +140,7 @@ env: 2. Verify token has `issue:write` permission 3. Check workflow logs for API errors -### @ai-bot edits the issue instead of replying +### @codebot edits the issue instead of replying **Causes:** - Workflow is using the wrong CLI command for comments @@ -149,7 +149,7 @@ env: **Solutions:** 1. Ensure your workflow uses the `comment` command for mentions: ```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)) diff --git a/docs/workflows.md b/docs/workflows.md index 1a21fce..639c140 100644 --- a/docs/workflows.md +++ b/docs/workflows.md @@ -1,21 +1,23 @@ # 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 | -|---------|--------|-------| -| Context variable | `github.*` | `gitea.*` | -| Default token | `GITHUB_TOKEN` | `AI_REVIEW_TOKEN` (custom) | -| API URL | `https://api.github.com` | Your Gitea instance URL | -| Tools location | Same repo (`tools/ai-review`) | Checkout from central repo | +| Feature | Configuration | +|---------|--------------| +| Context variable | `gitea.*` | +| Token | `AI_REVIEW_TOKEN` (custom secret) | +| API URL | Your Gitea instance URL (e.g., `https://git.example.com/api/v1`) | +| Tools location | Checkout from central OpenRabbit repo | + +All workflows are located in `.gitea/workflows/` directory. --- -## GitHub Workflows +## Gitea Workflows ### PR Review Workflow @@ -99,7 +101,7 @@ on: jobs: ai-reply: runs-on: ubuntu-latest - if: contains(github.event.comment.body, '@ai-bot') + if: contains(github.event.comment.body, '@codebot') steps: - uses: actions/checkout@v4 @@ -256,7 +258,7 @@ on: jobs: ai-reply: runs-on: ubuntu-latest - if: contains(github.event.comment.body, '@ai-bot') + if: contains(github.event.comment.body, '@codebot') steps: - uses: actions/checkout@v4 @@ -377,13 +379,13 @@ AI_REVIEW_API_URL: https://your-gitea.example.com/api/v1 ## 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. **Example usage:** ``` -@ai-bot How do I configure rate limiting? -@ai-bot Find all authentication-related files -@ai-bot What does the dispatcher module do? +@codebot How do I configure rate limiting? +@codebot Find all authentication-related files +@codebot What does the dispatcher module do? ``` diff --git a/tools/ai-review/agents/codebase_agent.py b/tools/ai-review/agents/codebase_agent.py index dde7486..494c4fc 100644 --- a/tools/ai-review/agents/codebase_agent.py +++ b/tools/ai-review/agents/codebase_agent.py @@ -96,7 +96,9 @@ class CodebaseAgent(BaseAgent): def execute(self, context: AgentContext) -> AgentResult: """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 = [] @@ -192,7 +194,7 @@ class CodebaseAgent(BaseAgent): # Check for docstrings (Python) if ext == ".py": - if 'def ' in content and '"""' not in content: + if "def " in content and '"""' not in content: metrics.missing_docstrings += 1 except Exception as e: @@ -273,23 +275,45 @@ Be constructive and actionable. Focus on the most impactful improvements. ) except Exception as e: self.logger.error(f"AI analysis failed: {e}") - # Try to log the raw response if possible (requires accessing the last response) - # 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. + self.logger.debug(f"Full error details: {type(e).__name__}: {str(e)}") + # Calculate basic health score from metrics health_score = 70 if metrics.todo_count > 10: health_score -= 10 if metrics.fixme_count > 5: 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( - 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, metrics=metrics, issues=[], - recommendations=["Manual review recommended"], - architecture_notes=[], + recommendations=recommendations, + architecture_notes=[ + f"Primary languages: {', '.join(list(metrics.languages.keys())[:3])}" + ], ) 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: """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 = [ f"{self.AI_DISCLAIMER}", @@ -427,7 +455,11 @@ Be constructive and actionable. Focus on the most impactful improvements. lines.append("") for issue in report.issues[:10]: 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("") lines.append(issue.get("description", "")) diff --git a/tools/ai-review/agents/issue_agent.py b/tools/ai-review/agents/issue_agent.py index 361ba0c..1c4e325 100644 --- a/tools/ai-review/agents/issue_agent.py +++ b/tools/ai-review/agents/issue_agent.py @@ -262,9 +262,7 @@ class IssueAgent(BaseAgent): if labels_to_add: try: self.gitea.add_issue_labels(owner, repo, issue_index, labels_to_add) - return [ - name for name, id in label_map.items() if id in labels_to_add - ] + return [name for name, id in label_map.items() if id in labels_to_add] except Exception as e: self.logger.warning(f"Failed to add labels: {e}") @@ -336,6 +334,8 @@ class IssueAgent(BaseAgent): return self._command_explain(title, body) elif command == "suggest": 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}`." @@ -390,3 +390,33 @@ Be practical and concise.""" return f"{self.AI_DISCLAIMER}\n\n**Suggestions:**\n{response.content}" except Exception as 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}" diff --git a/tools/ai-review/clients/llm_client.py b/tools/ai-review/clients/llm_client.py index d220be7..2e066fb 100644 --- a/tools/ai-review/clients/llm_client.py +++ b/tools/ai-review/clients/llm_client.py @@ -346,7 +346,9 @@ class LLMClient: config: Provider-specific configuration. """ 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.config = config or {} @@ -405,6 +407,8 @@ class LLMClient: Handles markdown code blocks and preamble text. """ + import re + content = content.strip() # Attempt 1: direct parse @@ -413,16 +417,24 @@ class LLMClient: except json.JSONDecodeError: pass - # Attempt 2: Extract from markdown code blocks + # Attempt 2: Extract from markdown code blocks (improved regex) if "```" in content: - # Find the JSON block - import re - match = re.search(r"```(?:json)?\s*([\s\S]*?)\s*```", content) - if match: - try: - return json.loads(match.group(1)) - except json.JSONDecodeError: - pass + # Try multiple code block patterns + patterns = [ + r"```json\s*\n([\s\S]*?)\n```", # ```json with newlines + r"```json\s*([\s\S]*?)```", # ```json without newlines + r"```\s*\n([\s\S]*?)\n```", # ``` with newlines + r"```\s*([\s\S]*?)```", # ``` without newlines + ] + + 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 } try: @@ -435,17 +447,22 @@ class LLMClient: pass # Attempt 4: Fix common JSON errors (comments, trailing commas) - # This is risky but helpful for LLM output try: # Remove comments - import re json_str = re.sub(r"//.*", "", content) json_str = re.sub(r"/\*[\s\S]*?\*/", "", json_str) - return json.loads(json_str) - except json.JSONDecodeError as e: - # 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: {e}. Raw content snippet: {snippet!r}") + # Try to extract JSON after cleaning + start = json_str.find("{") + end = json_str.rfind("}") + if start != -1 and end != -1: + 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 def from_config(cls, config: dict) -> "LLMClient": @@ -469,7 +486,9 @@ class LLMClient: } elif provider == "openrouter": 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), "max_tokens": config.get("max_tokens", 16000), } diff --git a/tools/ai-review/config.yml b/tools/ai-review/config.yml index bedd37c..801850b 100644 --- a/tools/ai-review/config.yml +++ b/tools/ai-review/config.yml @@ -1,49 +1,49 @@ -provider: openai # openai | openrouter | ollama +provider: openai # openai | openrouter | ollama model: - openai: gpt-4.1-mini - openrouter: anthropic/claude-3.5-sonnet - ollama: codellama:13b + openai: gpt-4.1-mini + openrouter: anthropic/claude-3.5-sonnet + ollama: codellama:13b temperature: 0 max_tokens: 4096 # Review settings review: - fail_on_severity: HIGH - max_diff_lines: 800 - inline_comments: true - security_scan: true + fail_on_severity: HIGH + max_diff_lines: 800 + inline_comments: true + security_scan: true # Agent settings agents: - issue: - enabled: true - auto_label: true - auto_triage: true - duplicate_threshold: 0.85 - events: - - opened - - labeled - pr: - enabled: true - inline_comments: true - security_scan: true - events: - - opened - - synchronize - codebase: - enabled: true - schedule: "0 0 * * 0" # Weekly on Sunday - chat: - enabled: true - name: "Bartender" - max_iterations: 5 # Max tool call iterations per chat - tools: - - search_codebase - - read_file - - search_web - searxng_url: "" # Set via SEARXNG_URL env var or here + issue: + enabled: true + auto_label: true + auto_triage: true + duplicate_threshold: 0.85 + events: + - opened + - labeled + pr: + enabled: true + inline_comments: true + security_scan: true + events: + - opened + - synchronize + codebase: + enabled: true + schedule: "0 0 * * 0" # Weekly on Sunday + chat: + enabled: true + name: "Bartender" + max_iterations: 5 # Max tool call iterations per chat + tools: + - search_codebase + - read_file + - search_web + searxng_url: "" # Set via SEARXNG_URL env var or here # Interaction settings # CUSTOMIZE YOUR BOT NAME HERE! @@ -56,41 +56,42 @@ agents: # NOTE: Also update the workflow files (.github/workflows/ or .gitea/workflows/) # to match this prefix in the 'if: contains(...)' condition interaction: - respond_to_mentions: true - mention_prefix: "@bartender" # Change this to customize your bot's name! - commands: - - explain - - suggest - - security - - summarize + respond_to_mentions: true + mention_prefix: "@codebot" # Change this to customize your bot's name! + commands: + - explain + - suggest + - security + - summarize + - triage # Enterprise settings enterprise: - audit_log: true - audit_path: "/var/log/ai-review/" - metrics_enabled: true - rate_limit: - requests_per_minute: 30 - max_concurrent: 4 + audit_log: true + audit_path: "/var/log/ai-review/" + metrics_enabled: true + rate_limit: + requests_per_minute: 30 + max_concurrent: 4 # Label mappings for auto-labeling labels: - priority: - high: "priority: high" - medium: "priority: medium" - low: "priority: low" - type: - bug: "type: bug" - feature: "type: feature" - question: "type: question" - docs: "type: documentation" - status: - ai_approved: "ai-approved" - ai_changes_required: "ai-changes-required" - ai_reviewed: "ai-reviewed" + priority: + high: "priority: high" + medium: "priority: medium" + low: "priority: low" + type: + bug: "type: bug" + feature: "type: feature" + question: "type: question" + docs: "type: documentation" + status: + ai_approved: "ai-approved" + ai_changes_required: "ai-changes-required" + ai_reviewed: "ai-reviewed" # Security scanning rules security: - enabled: true - fail_on_high: true - rules_file: "security/security_rules.yml" + enabled: true + fail_on_high: true + rules_file: "security/security_rules.yml"