Add GitHub integration for PRs, issues and AI PR description (#205)

* feat: integrate GitHub OAuth device flow across runtimes

Add GitHub OAuth device flow endpoints across runtimes
Introduce GitHubSettings UI panel and sidebar entry
Persist GitHub auth state in per-runtime storage

* feat: add GitHub PR status and PR description generation

Show PR status for the current branch in the Git view
Generate a pull request description from the diff between base and head
Expose prStatus, prCreate, and prMerge APIs in web and desktop clients

* feat: add GitHub PR ready for review

Add API to mark pull requests as ready for review
Show a Ready button for draft PRs and reflect status in UI
Handle token expiration and GraphQL errors when marking ready
This commit is contained in:
Bohdan Triapitsyn
2026-01-23 16:08:58 +02:00
committed by GitHub
parent 0e715be7d6
commit 463e9ec4e3
43 changed files with 4999 additions and 106 deletions
+42
View File
@@ -684,6 +684,48 @@ export async function getGitDiff(
return { diff: result.stdout };
}
/**
* Get diff between two refs for a file (base...head).
*/
export async function getGitRangeDiff(
directory: string,
base: string,
head: string,
filePath: string,
contextLines = 3
): Promise<{ diff: string }> {
const baseRef = (base || '').trim();
const headRef = (head || '').trim();
if (!baseRef || !headRef) {
return { diff: '' };
}
const args = ['diff', '--no-color', `-U${Math.max(0, contextLines)}`, `${baseRef}...${headRef}`, '--', filePath];
const result = await execGit(args, directory);
return { diff: result.stdout };
}
/**
* List files changed between two refs (base...head).
*/
export async function getGitRangeFiles(
directory: string,
base: string,
head: string
): Promise<string[]> {
const baseRef = (base || '').trim();
const headRef = (head || '').trim();
if (!baseRef || !headRef) {
return [];
}
const args = ['diff', '--name-only', `${baseRef}...${headRef}`];
const result = await execGit(args, directory);
if (result.exitCode !== 0) return [];
return String(result.stdout || '')
.split('\n')
.map((l) => l.trim())
.filter(Boolean);
}
/**
* Get file diff with original and modified content
*/