Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions .github/workflows/gemini-code-analysis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: Gemini Code Analysis

on:
workflow_dispatch:
inputs:
file_path:
description: 'Path to the file to analyze'
required: true
type: string
pull_request:
types: [opened, synchronize]

permissions:
contents: read
pull-requests: write

jobs:
analyze:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4
with:
persist-credentials: false

- name: Setup Node.js
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
node-version: '18'

- name: Run Gemini Analysis (Manual)
if: github.event_name == 'workflow_dispatch'
env:
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
run: |
if [ -z "$GEMINI_API_KEY" ]; then
echo "Warning: GEMINI_API_KEY secret is not set. Skipping analysis."
exit 0
fi
node scripts/gemini_agent.js "${{ github.event.inputs.file_path }}" --api-key="$GEMINI_API_KEY"

- name: Run Gemini Analysis (PR)
if: github.event_name == 'pull_request'
env:
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
run: |
if [ -z "$GEMINI_API_KEY" ]; then
echo "Warning: GEMINI_API_KEY secret is not set. Skipping analysis."
exit 0
fi

# Get list of changed files in the PR
CHANGED_FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | grep -E '\.(go|js|ts|sol)$' || true)

if [ -z "$CHANGED_FILES" ]; then
echo "No relevant files changed in this PR."
exit 0
fi

# Analyze each changed file
echo "$CHANGED_FILES" | while read -r file; do
if [ -f "$file" ]; then
echo "Analyzing $file..."
node scripts/gemini_agent.js "$file" --api-key="$GEMINI_API_KEY" || true
fi
done
83 changes: 83 additions & 0 deletions scripts/GEMINI_AGENT_README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Gemini Code Analysis Agent

This script uses Google's Gemini AI model to analyze code for potential vulnerabilities, best practice deviations, and mathematical instability.

## Features

- Analyzes code files using the Gemini 2.5 Flash Preview model
- Provides a Protocol Stability Score (1-10)
- Identifies potential flaws and security issues
- Suggests repaired code when issues are found

## Prerequisites

- Node.js 18+ (which includes built-in fetch support)
- A Google Gemini API key

## Usage

### Command Line

```bash
node scripts/gemini_agent.js <filepath> --api-key=<your_key>
```

Example:
```bash
node scripts/gemini_agent.js ./pkg/model/model.go --api-key=your_gemini_api_key
```

### GitHub Actions

The script can be run automatically via GitHub Actions:

1. **Manual Trigger**: Go to Actions → "Gemini Code Analysis" → Run workflow, and specify the file path
2. **Automatic PR Analysis**: The workflow will automatically analyze changed files in pull requests (if GEMINI_API_KEY secret is configured)

## Setting up the API Key

### For Local Development

```bash
node scripts/gemini_agent.js path/to/file.go --api-key=YOUR_API_KEY
```

### For GitHub Actions

Add `GEMINI_API_KEY` as a repository secret:

1. Go to your repository settings
2. Navigate to Secrets and variables → Actions
3. Add a new secret named `GEMINI_API_KEY`
4. Paste your Google Gemini API key

## Getting a Gemini API Key

1. Visit [Google AI Studio](https://makersuite.google.com/app/apikey)
2. Sign in with your Google account
3. Create a new API key
4. Copy the key for use with this script

## Output

The script will output:
- Protocol Stability Score (1-10)
- Summary of potential flaws
- Repaired code block (if issues are found)
- "NO REPAIR NEEDED" (if code is perfect)

## Error Handling

The script includes comprehensive error handling:
- Missing API key: Shows usage instructions
- Missing file: Shows file read error
- API failures: Shows detailed error message
- Network issues: Gracefully handles fetch failures

## Note

This is a conceptual implementation designed for protocol analysis. The script can be extended to:
- Write repaired code back to files
- Comment on GitHub PRs with analysis results
- Support batch analysis of multiple files
- Integrate with CI/CD pipelines
108 changes: 108 additions & 0 deletions scripts/gemini_agent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// --- Conceptual Gemini Agent Script (Node.js) ---

const fs = require('fs');
const path = require('path');

// NOTE: In a real Node.js environment, you would use an external library like
// 'node-fetch' for making HTTP requests, and potentially 'dotenv' for keys.
// For this example, we assume basic fetch is available or polyfilled.

const GEMINI_MODEL = 'gemini-2.5-flash-preview-09-2025';

// Use a simple prompt designed for code repair/analysis
const AGENT_SYSTEM_PROMPT = `Act as an elite protocol engineer specializing in ZK-Circuits and DAO stability. Analyze the provided code block for vulnerabilities, deviations from best practices, and mathematical instability.
1. Assign a **Protocol Stability Score (1-10)**.
2. Provide a brief summary of **Potential Flaws**.
3. If flaws exist, provide the **REPAIRED CODE BLOCK** only. Do not provide any conversational text before the repaired code. If the code is perfect, output 'NO REPAIR NEEDED'.`;

/**
* Executes the Gemini API call to analyze the given code snippet.
* @param {string} codeContent - The content of the file to analyze.
* @param {string} filePath - The name of the file being analyzed.
* @param {string} apiKey - The Gemini API key.
*/
async function runAnalysis(codeContent, filePath, apiKey) {
if (!apiKey) {
console.error("Error: GEMINI_API_KEY is missing. Check GitHub Secrets configuration.");
return;
}

const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent?key=${apiKey}`;

// The user query includes the file content to be analyzed
const userQuery = `Analyze the protocol code for ${filePath}:\n\n\`\`\`\n${codeContent}\n\`\`\``;

const payload = {
contents: [{ parts: [{ text: userQuery }] }],
systemInstruction: { parts: [{ text: AGENT_SYSTEM_PROMPT }] },
// For code analysis, grounding is usually not necessary unless you need real-time data
// tools: [{ "google_search": {} }],
};

let response;
try {
// Simple fetch example (replace with node-fetch in a real project)
response = await fetch(apiUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const result = await response.json();
const analysisText = result.candidates?.[0]?.content?.parts?.[0]?.text || "Agent failed to generate response.";

console.log(`\n### Protocol Analysis for ${filePath} ###`);
console.log(analysisText);

// --- DEEP THINK REPAIR LOGIC ---
// A real agent would look for the 'REPAIRED CODE BLOCK' and attempt to
// write it back to the file system or comment on the PR using the GitHub Token.
const hasRepairDecision = analysisText.includes('REPAIRED CODE BLOCK') || analysisText.includes('NO REPAIR NEEDED');
if (hasRepairDecision) {
console.log("Analysis Complete. Check output for repair instructions.");
}

} catch (error) {
console.error(`\n--- FAILED ANALYSIS for ${filePath} ---`);
console.error(`Gemini Agent Error: ${error.message}`);
}
}

/**
* Main execution function to handle command-line arguments.
*/
async function main() {
const filePath = process.argv[2];
const apiKeyArg = process.argv.find(arg => arg.startsWith('--api-key='));

if (!filePath || !apiKeyArg) {
console.error("Usage: node gemini_agent.js <filepath> --api-key=<your_key>");
return;
}

const apiKey = apiKeyArg.split('=')[1];

try {
const codeContent = fs.readFileSync(path.resolve(filePath), 'utf8');
await runAnalysis(codeContent, filePath, apiKey);
} catch (error) {
console.error(`Error reading file ${filePath}: ${error.message}`);
}
}

// Ensure fetch is available in Node.js environment
if (typeof fetch === 'undefined') {
try {
global.fetch = require('node-fetch'); // NOTE: This requires 'npm install node-fetch' in a real setup
} catch (err) {
console.error('Error: fetch is not available and node-fetch is not installed.');
console.error('Please use Node.js 18+ which has built-in fetch support, or install node-fetch.');
process.exit(1);
}
}

main();
Loading