Commit a2ee9ceb4551

Vincent Demeester <vincent@sbr.pm>
2026-02-09 10:36:58
feat(pi): added direct PR reference support to review extension
Enhanced the /review command to accept PR references directly without requiring the interactive selector. Supported formats include PR numbers, repository references (owner/repo#number), and GitHub URLs. This allows quick PR reviews via , , or full URLs, skipping the selector when the PR reference is already known.
1 parent e711729
Changed files (1)
dots
pi
agent
extensions
dots/pi/agent/extensions/review.ts
@@ -11,8 +11,10 @@
  *
  * Usage:
  * - `/review` - show interactive selector
- * - `/review pr 123` - review PR #123 (checks out locally)
- * - `/review pr https://github.com/owner/repo/pull/123` - review PR from URL
+ * - `/review 123` - review PR #123 (checks out locally)
+ * - `/review tektoncd/pipeline#123` - review PR #123 from tektoncd/pipeline
+ * - `/review https://github.com/owner/repo/pull/123` - review PR from URL
+ * - `/review pr 123` - review PR #123 (alternative syntax)
  * - `/review uncommitted` - review uncommitted changes directly
  * - `/review branch main` - review against main branch
  * - `/review commit abc123` - review specific commit
@@ -539,7 +541,7 @@ async function hasPendingChanges(pi: ExtensionAPI): Promise<boolean> {
 }
 
 /**
- * Parse a PR reference (URL or number) and return the PR number
+ * Parse a PR reference (URL, number, or owner/repo#number) and return the PR number
  */
 function parsePrReference(ref: string): number | null {
 	const trimmed = ref.trim();
@@ -558,6 +560,13 @@ function parsePrReference(ref: string): number | null {
 		return parseInt(urlMatch[1], 10);
 	}
 
+	// Try to extract from owner/repo#number format
+	// Format: tektoncd/pipeline#1234
+	const repoMatch = trimmed.match(/^[^/]+\/[^#]+#(\d+)$/);
+	if (repoMatch) {
+		return parseInt(repoMatch[1], 10);
+	}
+
 	return null;
 }
 
@@ -1176,7 +1185,15 @@ export default function reviewExtension(pi: ExtensionAPI) {
 	function parseArgs(args: string | undefined): ReviewTarget | { type: "pr"; ref: string } | null {
 		if (!args?.trim()) return null;
 
-		const parts = args.trim().split(/\s+/);
+		const trimmed = args.trim();
+
+		// Check if it looks like a PR reference (URL, number, or owner/repo#number)
+		// This allows `/review 123`, `/review https://...`, or `/review tektoncd/pipeline#1234`
+		if (parsePrReference(trimmed) !== null) {
+			return { type: "pr", ref: trimmed };
+		}
+
+		const parts = trimmed.split(/\s+/);
 		const subcommand = parts[0]?.toLowerCase();
 
 		switch (subcommand) {