Skip to content

Commit 04a741f

Browse files
committed
Started skeletoning out broadcasts
1 parent 9904d13 commit 04a741f

16 files changed

Lines changed: 1012 additions & 417 deletions

File tree

claude-agent-github-wiki/.env.example

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,13 @@ TRIGGER_SECRET_KEY=your_secret_key
66
# Claude API Key
77
# Get from https://console.anthropic.com
88
ANTHROPIC_API_KEY=your_anthropic_api_key
9+
10+
# Supabase Configuration
11+
# Get these from your Supabase project settings
12+
# https://app.supabase.com/project/_/settings/api
13+
SUPABASE_URL=your_supabase_project_url
14+
SUPABASE_PRIVATE_KEY=your_supabase_private_key # For backend use only - more secure than anon key
15+
16+
# Public Supabase keys for frontend (if needed)
17+
NEXT_PUBLIC_SUPABASE_URL=your_supabase_project_url
18+
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key

claude-agent-github-wiki/README.md

Lines changed: 157 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,188 @@
1-
# Repo Wiki Chat
1+
# GitHub Repository Chat with AI
22

3-
A Next.js 14 demo application that showcases how to chat with GitHub repositories using AI. Users can paste a GitHub URL, ask questions about the codebase, and see AI's reasoning and tool usage stream live.
3+
A production-ready Next.js application that enables real-time conversations with GitHub repositories using Claude AI. Built with Trigger.dev for background processing, Supabase for realtime messaging, and Claude Agent SDK for intelligent code analysis.
44

5-
## Features
5+
## Architecture Overview
66

7-
- **Landing Page**: Clean, modern interface with GitHub URL input and example repositories
8-
- **Chat Interface**: Real-time conversation with AI about repository code
9-
- **Tool Usage Visualization**: View AI's tool calls (Read, Grep, Bash) with expandable results
10-
- **Responsive Design**: Works seamlessly across desktop and mobile devices
11-
- **Mock Data**: Demo includes sample conversations showing typical AI analysis
7+
This application uses a hybrid architecture combining:
8+
- **Trigger.dev Realtime Streams v2** for streaming AI responses (main data pipeline)
9+
- **Supabase Broadcast** for sending questions to the AI (lightweight control plane)
10+
- **Claude Agent SDK** for repository analysis with tool usage
11+
- **Build Extensions** for containerized git operations
12+
13+
## Key Features
14+
15+
- **Two-Task System**:
16+
- Task 1: Clones repository with git build extension
17+
- Task 2: Long-running chat session that maintains repo in memory
18+
- **No Re-cloning**: Repository stays in memory for entire chat session (up to 60 minutes)
19+
- **Real-time Streaming**: AI responses stream live via Trigger.dev Streams v2
20+
- **Tool Usage Visualization**: See Claude using Bash, Grep, Read, and other tools
21+
- **Session Management**: Unique session IDs link clone and chat operations
1222

1323
## Tech Stack
1424

15-
- Next.js 14 (App Router)
16-
- TypeScript
17-
- Tailwind CSS
18-
- shadcn/ui components
19-
- React Markdown for message formatting
25+
- **Frontend**: Next.js 14 (App Router), TypeScript, Tailwind CSS, shadcn/ui
26+
- **Backend**: Trigger.dev v4 for task orchestration
27+
- **AI**: Claude Agent SDK with extended thinking
28+
- **Realtime**: Trigger.dev Streams v2 + Supabase Broadcast
29+
- **Build**: Trigger.dev build extensions with apt-get for git
2030

2131
## Getting Started
2232

23-
Install dependencies:
33+
### Prerequisites
34+
35+
1. Create accounts and get API keys:
36+
- [Trigger.dev](https://cloud.trigger.dev) - Project ref and secret key
37+
- [Anthropic](https://console.anthropic.com) - Claude API key
38+
- [Supabase](https://app.supabase.com) - Project URL and anon key
39+
40+
### Environment Setup
41+
42+
1. Copy the example environment file:
43+
```bash
44+
cp .env.example .env.local
45+
```
46+
47+
2. Add your API keys to `.env.local`:
48+
```env
49+
# Trigger.dev
50+
TRIGGER_PROJECT_REF=your_project_ref
51+
TRIGGER_SECRET_KEY=your_secret_key
52+
53+
# Claude API
54+
ANTHROPIC_API_KEY=your_anthropic_api_key
55+
56+
# Supabase
57+
SUPABASE_URL=your_supabase_project_url
58+
SUPABASE_ANON_KEY=your_supabase_anon_key
59+
NEXT_PUBLIC_SUPABASE_URL=your_supabase_project_url
60+
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
61+
```
62+
63+
### Installation
2464

2565
```bash
2666
npm install
2767
```
2868

29-
Run the development server:
69+
### Development
70+
71+
Run both the Next.js app and Trigger.dev dev server:
3072

3173
```bash
74+
# Terminal 1: Next.js
3275
npm run dev
76+
77+
# Terminal 2: Trigger.dev
78+
npx trigger.dev@latest dev
79+
```
80+
81+
Open [http://localhost:3000](http://localhost:3000)
82+
83+
### Deployment
84+
85+
Deploy to Trigger.dev:
86+
```bash
87+
npx trigger.dev@latest deploy
88+
```
89+
90+
Deploy Next.js to Vercel:
91+
```bash
92+
vercel deploy
93+
```
94+
95+
## How It Works
96+
97+
### Flow Diagram
98+
99+
```
100+
User enters GitHub URL
101+
102+
Task 1: clone-repo (with git build extension)
103+
104+
Returns { tempDir, sessionId, repoName }
105+
106+
Task 2: repo-chat-session (long-running, 60 min timeout)
107+
108+
Subscribes to Supabase channel for questions
109+
110+
User sends questions → Supabase → Task 2
111+
112+
Claude analyzes repo with tools
113+
114+
Responses stream via Trigger.dev Streams v2 → Frontend
33115
```
34116

35-
Open [http://localhost:3000](http://localhost:3000) in your browser.
117+
### Key Components
118+
119+
1. **Build Extension** (`trigger.config.ts`):
120+
- Installs git via apt-get in container
121+
- Enables shallow cloning without local git dependency
122+
123+
2. **Clone Task** (`trigger/clone-repo.ts`):
124+
- Performs shallow clone (`--depth=1`)
125+
- Generates unique session ID
126+
- Returns temp directory path
127+
128+
3. **Chat Session Task** (`trigger/repo-chat-session.ts`):
129+
- Maintains repo in memory for 60 minutes
130+
- Listens for questions via Supabase Broadcast
131+
- Streams responses via Trigger.dev Streams v2
132+
- Cleans up temp directory on exit
133+
134+
4. **Frontend** (`app/chat/[runId]/page.tsx`):
135+
- Sends questions via Supabase
136+
- Receives responses via Trigger.dev Streams
137+
- Displays tool usage and AI reasoning
36138

37139
## Project Structure
38140

39141
```
40142
app/
41-
├── page.tsx # Landing page with repo input
42-
├── chat/[runId]/ # Chat interface
43-
└── globals.css # Global styles
143+
├── page.tsx # Landing page
144+
├── chat/[runId]/page.tsx # Chat interface
145+
└── api/
146+
├── analyze-repo/ # Triggers both tasks
147+
└── chat/ # Sends questions via Supabase
148+
149+
trigger/
150+
├── clone-repo.ts # Task 1: Git clone
151+
├── repo-chat-session.ts # Task 2: Long-running chat
152+
└── agent-stream.ts # Shared stream definition
44153
45154
components/
46-
├── chat/
47-
│ ├── user-message.tsx # User message bubble
48-
│ ├── ai-message.tsx # AI response bubble with markdown
49-
│ └── tool-card.tsx # Tool call visualization
50-
└── ui/ # shadcn/ui components
155+
├── chat/
156+
│ ├── user-message.tsx # User message display
157+
│ ├── ai-message.tsx # AI response with markdown
158+
│ └── tool-card.tsx # Tool usage visualization
159+
└── ui/ # shadcn/ui components
51160
```
52161

53-
## Usage
162+
## Advanced Features
163+
164+
- **60-minute sessions**: Extended timeout for complex analysis
165+
- **Abort handling**: Graceful cleanup on cancellation
166+
- **Error recovery**: Fallback to Trigger.dev streams if Supabase fails
167+
- **Progress tracking**: Real-time status updates
168+
- **Tool visualization**: Collapsible tool results over 50 lines
169+
170+
## Limitations
171+
172+
- Public repositories only (no auth for private repos)
173+
- Maximum session duration: 60 minutes
174+
- Shallow clone only (no full git history)
175+
- One active question at a time per session
176+
177+
## Development Notes
54178

55-
1. Visit the landing page
56-
2. Enter a GitHub repository URL or click one of the example repos
57-
3. Ask questions about the repository's code, features, or architecture
58-
4. Watch as the AI analyzes the codebase and provides insights
179+
This demo showcases:
180+
- Trigger.dev Realtime Streams v2 for data streaming
181+
- Build extensions for containerized dependencies
182+
- Hybrid architecture pattern (control + data plane separation)
183+
- Long-running task management
184+
- Claude Agent SDK integration
59185

60-
## Note
186+
## License
61187

62-
This is a demo application with mock data. In a production implementation, it would integrate with an actual AI service and GitHub API to provide real repository analysis.
188+
MIT

claude-agent-github-wiki/app/api/analyze-repo/route.ts

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import { tasks } from "@trigger.dev/sdk/v3";
1+
import { tasks, runs } from "@trigger.dev/sdk/v3";
22
import { cloneRepo } from "@/trigger/clone-repo";
3+
import { repoChatSession } from "@/trigger/repo-chat-session";
34
import { NextRequest, NextResponse } from "next/server";
45

56
export async function POST(request: NextRequest) {
@@ -24,14 +25,61 @@ export async function POST(request: NextRequest) {
2425
}
2526

2627
// Trigger the clone task
27-
const handle = await tasks.trigger<typeof cloneRepo>(
28+
const cloneHandle = await tasks.trigger<typeof cloneRepo>(
2829
"clone-repo",
2930
{ githubUrl }
3031
);
3132

32-
// Return the run ID to track clone progress
33+
// Wait for clone to complete using pollForCompletion
34+
let cloneResult;
35+
let attempts = 0;
36+
const maxAttempts = 60; // 60 seconds timeout
37+
38+
while (attempts < maxAttempts) {
39+
const run = await runs.retrieve<typeof cloneRepo>(cloneHandle.id);
40+
41+
if (run.status === "COMPLETED" && run.output) {
42+
cloneResult = { ok: true, output: run.output };
43+
break;
44+
} else if (run.status === "FAILED") {
45+
return NextResponse.json(
46+
{ error: "Failed to clone repository" },
47+
{ status: 500 }
48+
);
49+
}
50+
51+
// Wait 1 second before next check
52+
await new Promise(resolve => setTimeout(resolve, 1000));
53+
attempts++;
54+
}
55+
56+
if (!cloneResult) {
57+
return NextResponse.json(
58+
{ error: "Clone operation timed out" },
59+
{ status: 500 }
60+
);
61+
}
62+
63+
// Immediately trigger chat session with the cloned repo
64+
const chatHandle = await tasks.trigger<typeof repoChatSession>(
65+
"repo-chat-session",
66+
{
67+
tempDir: cloneResult.output.tempDir,
68+
sessionId: cloneResult.output.sessionId,
69+
repoName: cloneResult.output.repoName,
70+
}
71+
);
72+
73+
// Get public access token from handle (auto-generated, expires in 15 min)
74+
const accessToken = chatHandle.publicAccessToken;
75+
76+
// Return session details
3377
return NextResponse.json({
34-
cloneRunId: handle.id,
78+
sessionId: cloneResult.output.sessionId,
79+
chatRunId: chatHandle.id,
80+
accessToken,
81+
repoName: cloneResult.output.repoName,
82+
cloneRunId: cloneHandle.id, // Keep for backward compatibility
3583
});
3684

3785
} catch (error: any) {

0 commit comments

Comments
 (0)