From 5efa6aadfe3fd79ebe1def3709faf7e490827660 Mon Sep 17 00:00:00 2001 From: Michael Ramos Date: Mon, 9 Mar 2026 22:56:26 -0700 Subject: [PATCH 1/2] feat: add Pi origin support to code review UI and update banner Pi users were seeing "OpenCode" badge and getting the wrong update command. Adds 'pi' to origin types in review/annotate servers, shows violet "Pi" badge in code review header, and copies the correct `pi install` command in the update banner. Co-Authored-By: Claude Opus 4.6 --- packages/review-editor/App.tsx | 18 ++++++++++-------- packages/server/annotate.ts | 2 +- packages/server/review.ts | 2 +- packages/ui/components/UpdateBanner.tsx | 14 +++++++++++--- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/packages/review-editor/App.tsx b/packages/review-editor/App.tsx index c04200cf6..ab7bad579 100644 --- a/packages/review-editor/App.tsx +++ b/packages/review-editor/App.tsx @@ -35,7 +35,7 @@ interface DiffData { files: DiffFile[]; rawPatch: string; gitRef: string; - origin?: 'opencode' | 'claude-code'; + origin?: 'opencode' | 'claude-code' | 'pi'; diffType?: string; gitContext?: GitContext; sharingEnabled?: boolean; @@ -139,7 +139,7 @@ const ReviewApp: React.FC = () => { const [copyFeedback, setCopyFeedback] = useState(null); const [viewedFiles, setViewedFiles] = useState>(new Set()); const [hideViewedFiles, setHideViewedFiles] = useState(false); - const [origin, setOrigin] = useState<'opencode' | 'claude-code' | null>(null); + const [origin, setOrigin] = useState<'opencode' | 'claude-code' | 'pi' | null>(null); const [diffType, setDiffType] = useState('uncommitted'); const [gitContext, setGitContext] = useState(null); const [isLoadingDiff, setIsLoadingDiff] = useState(false); @@ -214,7 +214,7 @@ const ReviewApp: React.FC = () => { .then((data: { rawPatch: string; gitRef: string; - origin?: 'opencode' | 'claude-code'; + origin?: 'opencode' | 'claude-code' | 'pi'; diffType?: string; gitContext?: GitContext; sharingEnabled?: boolean; @@ -615,9 +615,11 @@ const ReviewApp: React.FC = () => { )} {repoInfo && ( @@ -991,10 +993,10 @@ const ReviewApp: React.FC = () => { title={submitted === 'approved' ? 'Changes Approved' : 'Feedback Sent'} subtitle={ submitted === 'approved' - ? `${origin === 'claude-code' ? 'Claude Code' : 'OpenCode'} will proceed with the changes.` - : `${origin === 'claude-code' ? 'Claude Code' : 'OpenCode'} will address your review feedback.` + ? `${origin === 'claude-code' ? 'Claude Code' : origin === 'pi' ? 'Pi' : 'OpenCode'} will proceed with the changes.` + : `${origin === 'claude-code' ? 'Claude Code' : origin === 'pi' ? 'Pi' : 'OpenCode'} will address your review feedback.` } - agentLabel={origin === 'claude-code' ? 'Claude Code' : 'OpenCode'} + agentLabel={origin === 'claude-code' ? 'Claude Code' : origin === 'pi' ? 'Pi' : 'OpenCode'} /> {/* Update notification */} diff --git a/packages/server/annotate.ts b/packages/server/annotate.ts index 1f425ad92..28a380e56 100644 --- a/packages/server/annotate.ts +++ b/packages/server/annotate.ts @@ -31,7 +31,7 @@ export interface AnnotateServerOptions { /** HTML content to serve for the UI */ htmlContent: string; /** Origin identifier for UI customization */ - origin?: "opencode" | "claude-code"; + origin?: "opencode" | "claude-code" | "pi"; /** Whether URL sharing is enabled (default: true) */ sharingEnabled?: boolean; /** Custom base URL for share links */ diff --git a/packages/server/review.ts b/packages/server/review.ts index 2cc50a387..bb16c9f91 100644 --- a/packages/server/review.ts +++ b/packages/server/review.ts @@ -34,7 +34,7 @@ export interface ReviewServerOptions { /** HTML content to serve for the UI */ htmlContent: string; /** Origin identifier for UI customization */ - origin?: "opencode" | "claude-code"; + origin?: "opencode" | "claude-code" | "pi"; /** Current diff type being displayed */ diffType?: DiffType; /** Git context with branch info and available diff options */ diff --git a/packages/ui/components/UpdateBanner.tsx b/packages/ui/components/UpdateBanner.tsx index 3c70ee900..4b102b4ee 100644 --- a/packages/ui/components/UpdateBanner.tsx +++ b/packages/ui/components/UpdateBanner.tsx @@ -1,7 +1,8 @@ import React, { useState } from 'react'; import { useUpdateCheck } from '../hooks/useUpdateCheck'; -const INSTALL_COMMAND = 'curl -fsSL https://plannotator.ai/install.sh | bash'; +const DEFAULT_INSTALL_COMMAND = 'curl -fsSL https://plannotator.ai/install.sh | bash'; +const PI_INSTALL_COMMAND = 'pi install npm:@plannotator/pi-extension'; interface UpdateBannerProps { origin?: 'claude-code' | 'opencode' | 'pi' | null; @@ -16,13 +17,15 @@ export const UpdateBanner: React.FC = ({ origin }) => { const urlParams = new URLSearchParams(window.location.search); const previewOrigin = urlParams.get('preview-origin'); const effectiveOrigin = previewOrigin || origin; + const isPi = effectiveOrigin === 'pi'; const isOpenCode = effectiveOrigin === 'opencode'; + const installCommand = isPi ? PI_INSTALL_COMMAND : DEFAULT_INSTALL_COMMAND; if (!updateInfo?.updateAvailable || dismissed) return null; const handleCopy = async () => { try { - await navigator.clipboard.writeText(INSTALL_COMMAND); + await navigator.clipboard.writeText(installCommand); setCopied(true); setTimeout(() => setCopied(false), 2000); } catch (e) { @@ -76,12 +79,17 @@ export const UpdateBanner: React.FC = ({ origin }) => { You have {updateInfo.currentVersion}

- {/* OpenCode extra instructions */} + {/* Agent-specific extra instructions */} {isOpenCode && (

Run the install script, then restart OpenCode.

)} + {isPi && ( +

+ Run the install command, then restart Pi. +

+ )}