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
144 changes: 144 additions & 0 deletions .github/AI_PR_SETUP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
# AI-Generated Pull Request Setup

This guide describes how to configure automatic PR creation with AI-generated code suggestions for feature requests.

## Overview

When an issue is created with the `enhancement` label, the workflow will:

1. **Enhance the issue description** - Convert to structured user story format
2. **Create Confluence page** (optional) - Document requirements
3. **Generate implementation with Claude AI** - Analyze codebase and create implementation plan
4. **Create automatic PR** - Commit implementation plan and create PR against `develop` branch

## Configuration

### 1. GitHub Secrets

You need to configure the following secrets in your GitHub repository:

**Settings → Secrets and variables → Actions → New repository secret**

#### Required for AI-PR:
- `ANTHROPIC_API_KEY` - Your Anthropic API key for Claude
- Get from: https://console.anthropic.com/
- Format: `sk-ant-api03-...`

#### Optional (for enhanced features):
- `OPENAI_API_KEY` - For preprocessing with OpenAI
- `PREPROCESSING_MODEL` - Optional, default: `gpt-4o-mini`
- `CLAUDE_MODEL` - Optional, default: `claude-sonnet-4-5-20250929`

#### Optional (for Confluence integration):
- `CONFLUENCE_URL` - Your Confluence URL (e.g. `https://your-domain.atlassian.net`)
- `CONFLUENCE_EMAIL` - Your Confluence account email
- `CONFLUENCE_API_TOKEN` - Confluence API token
- `CONFLUENCE_SPACE_KEY` - Space key where pages should be created (default: `AICODE`)
- `CONFLUENCE_PARENT_PAGE_ID` - Parent page ID (optional)

### 2. GitHub CLI (gh) Access

The workflow uses `gh` CLI to create PRs. This works automatically with `GITHUB_TOKEN` provided by GitHub Actions.

### 3. Repository Permissions

Verify that GitHub Actions has the correct permissions:

**Settings → Actions → General → Workflow permissions**
- Select: "Read and write permissions"
- Enable: "Allow GitHub Actions to create and approve pull requests"

## Usage

### Create a Feature Request

1. Go to **Issues → New Issue**
2. Write your feature request
3. Add the **`enhancement`** label
4. Create the issue

### What Happens Automatically

The workflow will:

1. ✅ Enhance issue description with structured user story
2. 📄 Create a Confluence page (if configured)
3. 🤖 Use Claude AI to analyze the codebase
4. 📝 Generate an implementation plan
5. 🌿 Create a new branch: `feature/issue-{number}-implementation`
6. 📤 Commit the file `implementation-{number}.md`
7. 🔀 Create a PR against `develop` branch
8. 💬 Comment on original issue with PR link

### PR Content

The PR will contain:
- A markdown file with Claude's implementation plan
- Analysis of existing code
- Suggestions for which files need changes
- Concrete code examples and instructions

### Next Steps After PR Creation

1. **Review the implementation plan** in the PR
2. **Add actual code changes** based on the plan
3. **Test the implementation**
4. **Merge when ready**

## Manual Trigger

You can also trigger the workflow manually:

1. Go to **Actions → Enhance Feature Requests**
2. Click **Run workflow**
3. Enter issue number
4. Click **Run workflow**

## Troubleshooting

### Workflow Doesn't Run

- Verify that issue has the `enhancement` label
- Check that workflow file exists in main/master branch
- Review Actions log for error messages

### PR Not Created

- Verify that `ANTHROPIC_API_KEY` is configured
- Check that repository has correct permissions (see step 3 above)
- Verify that `gh` CLI works in workflow log

### Low Quality Implementation

- Try using `claude-opus-4.5` instead: set secret `CLAUDE_MODEL=claude-opus-4.5-20251101`
- Ensure issue description is clear and detailed
- Add more context in [generate-implementation.mjs](.github/agent/generate-implementation.mjs)

## Cost

- **Anthropic Claude API**: ~$0.50-2.00 per feature request (depending on model)
- **OpenAI** (optional): ~$0.01-0.10 per preprocessing
- **GitHub Actions**: Free for public repos, included in private repo plans

## Customize the Implementation Generator

Edit [.github/agent/generate-implementation.mjs](.github/agent/generate-implementation.mjs) to:

- Add more project files for context
- Modify system prompt for better output
- Customize how implementation is presented

## Branch Strategy

**Important**: All PRs are automatically created against the `develop` branch. This is configured in the workflow at line 354:

```yaml
--base develop \
```

If you need to change the target branch, modify this line in [.github/workflows/feature-request-enhance.yml](.github/workflows/feature-request-enhance.yml).

## Support

- GitHub Issues: https://github.com/htilly/SlackONOS/issues
- Claude API Docs: https://docs.anthropic.com/
184 changes: 184 additions & 0 deletions .github/agent/generate-implementation.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
import Anthropic from "@anthropic-ai/sdk";
import { readFileSync, writeFileSync, existsSync } from "fs";
import { resolve, dirname } from "path";
import { fileURLToPath } from "url";

const __dirname = dirname(fileURLToPath(import.meta.url));

/**
* Generate Implementation - Use Claude to analyze codebase and generate implementation
*
* This script uses Claude to:
* 1. Analyze the existing codebase
* 2. Generate an implementation plan
* 3. Create code changes for the feature request
*/

const enhancedTask = process.env.ENHANCED_TASK || process.env.TASK || "";
const issueNumber = process.env.ISSUE_NUMBER || "unknown";
const anthropicApiKey = process.env.ANTHROPIC_API_KEY;
const model = process.env.CLAUDE_MODEL || "claude-sonnet-4-5-20250929";

if (!enhancedTask) {
console.error("[IMPLEMENTATION] ENHANCED_TASK or TASK environment variable not set");
process.exit(1);
}

if (!anthropicApiKey) {
console.error("[IMPLEMENTATION] ANTHROPIC_API_KEY not set");
process.exit(1);
}

const anthropic = new Anthropic({ apiKey: anthropicApiKey });

/**
* Read relevant project files to give Claude context
*/
function getProjectContext() {
const repoRoot = resolve(__dirname, "../..");
const files = [];

// Read package.json for dependencies
try {
const packageJson = readFileSync(resolve(repoRoot, "package.json"), "utf8");
files.push({
path: "package.json",
content: packageJson
});
} catch (e) {
console.warn("[IMPLEMENTATION] Could not read package.json");
}

// Read main index file
try {
const indexJs = readFileSync(resolve(repoRoot, "index.js"), "utf8");
files.push({
path: "index.js",
content: indexJs.substring(0, 5000) // First 5000 chars to avoid token limits
});
} catch (e) {
console.warn("[IMPLEMENTATION] Could not read index.js");
}

// Read lib directory structure
try {
const libFiles = [
"lib/slack.js",
"lib/discord.js",
"lib/voting.js",
"lib/command-handlers.js",
"lib/ai-handler.js",
"lib/spotify.js"
];

for (const libFile of libFiles) {
const fullPath = resolve(repoRoot, libFile);
if (existsSync(fullPath)) {
const content = readFileSync(fullPath, "utf8");
files.push({
path: libFile,
content: content.substring(0, 3000) // First 3000 chars per file
});
}
}
} catch (e) {
console.warn("[IMPLEMENTATION] Could not read lib files");
}

return files;
}

/**
* Generate implementation using Claude
*/
async function generateImplementation() {
try {
console.log(`[IMPLEMENTATION] Generating implementation with ${model}...`);
console.log(`[IMPLEMENTATION] Feature request: ${enhancedTask}`);

const projectFiles = getProjectContext();

// Build context from project files
let contextText = "Here are relevant files from the project:\n\n";
for (const file of projectFiles) {
contextText += `--- ${file.path} ---\n${file.content}\n\n`;
}

const systemPrompt = `You are an expert software developer working on a Slack/Discord bot for controlling Sonos speakers.

The project is called SlackONOS and is a democratic bot where users can vote on songs to play.

Your task is to analyze the feature request and generate a concrete implementation plan with code suggestions.

Project context:
- Node.js application
- Uses Slack Socket Mode / Events API (via @slack/socket-mode) and Discord.js
- Controls Sonos speakers
- Has voting system for democratic music control
- Uses AI for natural language commands
- Supports Spotify integration

Output format:
1. **Implementation Plan** - Brief overview of what needs to be changed
2. **Files to Modify/Create** - List specific files
3. **Code Changes** - Provide actual code snippets or full file contents

Be specific and actionable. Focus on the actual code changes needed.`;

const userPrompt = `Feature Request to Implement:

${enhancedTask}

${contextText}

Please provide:
1. A brief implementation plan
2. List of files to modify or create
3. Actual code changes with clear instructions

Make it actionable and ready to commit.`;

const response = await anthropic.messages.create({
model: model,
max_tokens: 4096,
messages: [
{
role: "user",
content: [
{
type: "text",
text: `${systemPrompt}\n\n${userPrompt}`
}
]
}
]
});

const implementation = response.content[0].text;

console.log(`[IMPLEMENTATION] Generated implementation plan:`);
console.log(implementation);

// Save implementation to file for the workflow to use
const outputPath = resolve(__dirname, `../../implementation-${issueNumber}.md`);
writeFileSync(outputPath, implementation, "utf8");
console.log(`[IMPLEMENTATION] Saved to ${outputPath}`);

// Output markers for workflow parsing
console.log(`\nIMPLEMENTATION_FILE:${outputPath}`);
console.log(`IMPLEMENTATION_START`);
console.log(implementation);
console.log(`IMPLEMENTATION_END`);

return implementation;

} catch (error) {
console.error(`[IMPLEMENTATION] Error generating implementation: ${error.message}`);
if (error.response) {
console.error(`[IMPLEMENTATION] API Error: ${JSON.stringify(error.response.data)}`);
}
process.exit(1);
}
}

generateImplementation();
Loading
Loading