Here's a comprehensive implementation plan for issue #240, based on the existing codebase .
The PR view already has solid foundations to build on :
| Component | Status | Location |
|---|---|---|
| File diff viewer | ✅ Working | FileDetailView.tsx → DiffViewer |
| PR details view | ✅ Working | PrDetailsView.tsx |
| PR store (files, branches) | ✅ Working | src/views/pr/stores/ |
| GitHub write ops | ✅ Partial | githubWrite.ts — has PR creation but no review endpoints |
| GitHub API (Rust) | ✅ Partial | github_api.rs (34KB) + pr_context.rs + pr_files.rs — no review API yet |
| Review/comment endpoints | ❌ Missing | Nothing in Rust or TS for posting PR review comments |
The GitHub Pull Request Review API has three operations you need. Add these to github_api.rs or a new github_review.rs :
// src-tauri/src/github_review.rs (new file)
/// Create a review with inline comments
/// POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews
#[tauri::command]
pub async fn github_create_pr_review(
owner: String,
repo: String,
pull_number: u64,
body: String, // Top-level review summary
event: String, // "APPROVE" | "REQUEST_CHANGES" | "COMMENT"
comments: Vec<ReviewComment>, // Inline comments
github_token: tauri::State<'_, GithubToken>,
) -> Result<ReviewResponse, String> {
// POST to /repos/{owner}/{repo}/pulls/{pull_number}/reviews
// Body: { body, event, comments: [{ path, position, body }] }
}
#[derive(Serialize, Deserialize, Clone)]
pub struct ReviewComment {
pub path: String, // file path relative to repo root
pub line: u32, // line number in the diff
pub side: String, // "LEFT" (old) or "RIGHT" (new)
pub body: String, // the review comment text
}
/// Also useful: fetch existing review comments for display
/// GET /repos/{owner}/{repo}/pulls/{pull_number}/comments
#[tauri::command]
pub async fn github_list_pr_review_comments(
owner: String,
repo: String,
pull_number: u64,
github_token: tauri::State<'_, GithubToken>,
) -> Result<Vec<ExistingReviewComment>, String> { ... }The GitHub Review API requires position (line offset within the diff hunk), not absolute line numbers. You can compute this from the diff hunks you already have in pr_files.rs .
Register in main.rs alongside the existing GitHub commands .
Extend githubWrite.ts with review operations :
// Add to src/services/githubWrite.ts
export interface ReviewComment {
path: string;
line: number;
side: 'LEFT' | 'RIGHT';
body: string;
}
export interface CreateReviewOptions {
owner: string;
repo: string;
pull_number: number;
body: string;
event: 'APPROVE' | 'REQUEST_CHANGES' | 'COMMENT';
comments: ReviewComment[];
}
export interface ReviewInfo {
id: number;
body: string;
state: string;
html_url: string;
user: string;
submitted_at: string;
}
export async function createPRReview(
options: CreateReviewOptions
): Promise<ReviewInfo> {
return invoke<ReviewInfo>('github_create_pr_review', {
owner: options.owner,
repo: options.repo,
pullNumber: options.pull_number,
body: options.body,
event: options.event,
comments: options.comments,
});
}This is where Omni's 6-source enrichment pipeline gives you the edge over every other review tool . Create a new service:
// src/services/reviewGenerator.ts (new file)
interface ReviewRequest {
owner: string;
repo: string;
pullNumber: number;
repoPath: string; // local repo path
baseBranch: string;
headBranch: string;
userPrompt?: string; // optional guidance from prompt overlay
}
interface GeneratedReview {
summary: string; // top-level review body
comments: ReviewComment[]; // inline per-file comments
event: 'APPROVE' | 'REQUEST_CHANGES' | 'COMMENT';
}
export async function generateAIReview(
request: ReviewRequest
): Promise<GeneratedReview> {
// Step 1: Gather context from all 6 sources
// - diff: reuse getPrFileDiff() from fileViewerService
// - files: read related project files via Tauri
// - web: crawl referenced docs/APIs (existing web crawler)
// - connectors: PR → issue chain via pr_context.rs
// - agent input: check for recent agent transcript
// - human input: userPrompt from prompt overlay
// Step 2: Build per-file dossiers (same pattern as AI Rebase)
// For each changed file:
// - diff hunks
// - related project files (imports, tests)
// - issue/PR context
// Step 3: AI generates review per file (recursive, AFM-compatible)
// For each file dossier, ask the LLM:
// - Any bugs or issues?
// - Does the change align with the linked issue?
// - Style/architecture concerns?
// - What line(s) to comment on?
// Step 4: AI generates overall summary
// Roll up individual file reviews into a cohesive summary
return { summary, comments, event };
}The per-file approach keeps token budgets small (same principle as the recursive grouping in AI Rebase) — you can review a 200-file PR without blowing up AFM context windows .
Add a "Review PR" action to the existing PR view layout :
// src/views/pr/components/ui/ReviewButton.tsx (new file)
export const ReviewButton: FC = () => {
const { isGenerating, generateReview, generatedReview } = useReview();
return (
<button onClick={generateReview} disabled={isGenerating}>
{isGenerating ? 'Reviewing...' : '✦ AI Review'}
</button>
);
};The biggest UI change: extend FileDetailView.tsx and the DiffViewer component to show and add inline comments :
// Extend the DiffViewer component to accept review comments
<DiffViewer
fileName={diffData.file_name}
fileLang={diffData.file_lang}
oldContent={diffData.old_content}
newContent={diffData.new_content}
diffHunks={diffData.diff_hunks}
theme="light"
// NEW PROPS:
reviewComments={commentsForFile} // show AI-generated comments inline
onAddComment={(line, side, body) => { // allow manual additions
addComment({ path: file.path, line, side, body });
}}
/>Each comment renders as a collapsible annotation below the relevant diff line — similar to GitHub's own review UI but within Omni.
Before posting to GitHub, show a preview:
// src/views/pr/components/overlays/ReviewPreview.tsx (new file)
export const ReviewPreview: FC = () => {
const { generatedReview, submitReview, editComment, removeComment } = useReview();
// Shows:
// 1. Summary text (editable)
// 2. List of inline comments with file path + line (editable, removable)
// 3. Event selector: Approve / Request Changes / Comment
// 4. Submit button → calls createPRReview()
};// src/views/pr/stores/reviewStore.ts (new file)
interface ReviewStore {
isGenerating: boolean;
generatedReview: GeneratedReview | null;
existingComments: ExistingReviewComment[]; // fetched from GitHub
// Actions
generateReview: () => Promise<void>;
editSummary: (text: string) => void;
editComment: (index: number, body: string) => void;
removeComment: (index: number) => void;
addComment: (comment: ReviewComment) => void;
submitReview: () => Promise<void>; // posts to GitHub
reset: () => void;
}As described in the blog post, the CLI path omni --pr --review would reuse the same generateAIReview() logic. Add a handler in cli_settings.rs :
// In cli_settings.rs, add:
"--pr" => {
if args.contains("--review") {
// 1. Detect current branch → find open PR
// 2. Gather 6-source context
// 3. Generate review via AI
// 4. POST review to GitHub
// 5. Print: "Review posted. [done]"
}
}User clicks "AI Review" (or runs omni --pr --review)
|
v
[ Gather 6-source context per file ]
- diff, project files, web, connectors, agent transcript, human input
|
v
[ AI generates per-file comments ] (recursive, AFM-compatible)
|
v
[ AI generates overall summary ]
|
v
[ Preview in UI — user edits/approves ]
|
v
[ POST to GitHub Reviews API ]
|
v
Review appears on PR under @user's name
src-tauri/src/github_review.rs # Rust: GitHub Review API endpoints
src/services/reviewGenerator.ts # TS: 6-source AI review generation
src/views/pr/stores/reviewStore.ts # TS: review state management
src/views/pr/components/ui/ReviewButton.tsx # UI: trigger button
src/views/pr/components/overlays/ReviewPreview.tsx # UI: preview & edit before submit
src/views/pr/hooks/useReview.ts # Hook: wires store → services → Tauri
- Review posts under the authenticated user's name — not a bot account. This is critical for trust, as your blog post emphasizes .
- Per-file AI calls, not whole-PR — keeps AFM token budgets manageable and mirrors the recursive approach from AI Rebase.
- Human-in-the-loop — AI generates, user previews and edits, then submits. No auto-posting without review.
- Reuse the 6-source pipeline — the context-gathering infrastructure from commit enrichment (
pr_context.rs, web crawler, etc.) feeds directly into review generation . - The
DiffViewercomponent is the integration surface — it already renders per-file diffs with old/new content and hunks. Adding inline comment annotations is the natural extension .