diff --git a/ROADMAP.md b/ROADMAP.md
index 8ad4ed9..35176eb 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -83,8 +83,8 @@ Implemented foundation:
Still worth adding:
-- [ ] outdated Copilot CLI state
-- [ ] active GitHub account or organization context when available
+- [x] outdated Copilot CLI state
+- [x] active GitHub account or organization context when available
- [ ] clear model availability explanation when a model is unavailable
- [ ] reconnect and troubleshooting actions beyond refresh
- [ ] optional per-project or per-pattern account selection later if Kopaya supports multiple Copilot identities
diff --git a/src/renderer/components/CopilotStatusCard.tsx b/src/renderer/components/CopilotStatusCard.tsx
index 1ed9db2..5acab19 100644
--- a/src/renderer/components/CopilotStatusCard.tsx
+++ b/src/renderer/components/CopilotStatusCard.tsx
@@ -9,11 +9,15 @@ import {
LogIn,
Download,
Cpu,
+ ArrowUpCircle,
+ User,
+ Building2,
} from 'lucide-react';
import type {
SidecarConnectionDiagnostics,
SidecarConnectionStatus,
+ SidecarCopilotCliVersionStatus,
} from '@shared/contracts/sidecar';
interface CopilotStatusCardProps {
@@ -94,6 +98,85 @@ function shortenPath(fullPath: string): string {
return `…/${parts.slice(-2).join('/')}`;
}
+function VersionBadge({ status, installedVersion }: { status: SidecarCopilotCliVersionStatus; installedVersion?: string }) {
+ const versionLabel = installedVersion ? `v${installedVersion}` : undefined;
+
+ switch (status) {
+ case 'latest':
+ return (
+
+
+ {versionLabel ?? 'Up to date'}
+
+ );
+ case 'outdated':
+ return (
+
+
+ Update available
+
+ );
+ case 'unknown':
+ return (
+
+ {versionLabel ?? 'Version unknown'}
+
+ );
+ }
+}
+
+function AccountSection({ connection }: { connection: SidecarConnectionDiagnostics }) {
+ const { account } = connection;
+ if (!account) return null;
+
+ const hasLogin = !!account.login;
+ const hasOrgs = account.organizations && account.organizations.length > 0;
+ if (!hasLogin && !account.statusMessage) return null;
+
+ const MAX_VISIBLE_ORGS = 5;
+ const visibleOrgs = hasOrgs ? account.organizations!.slice(0, MAX_VISIBLE_ORGS) : [];
+ const remainingOrgs = hasOrgs ? account.organizations!.length - MAX_VISIBLE_ORGS : 0;
+
+ return (
+
+ {/* Identity row */}
+
+
+ {hasLogin ? (
+
+ {account.login}
+ {account.host && (
+ · {account.host}
+ )}
+
+ ) : (
+
{account.statusMessage}
+ )}
+
+
+ {/* Organizations */}
+ {hasOrgs && (
+
+
+
+ {visibleOrgs.map((org) => (
+
+ {org}
+
+ ))}
+ {remainingOrgs > 0 && (
+ +{remainingOrgs} more
+ )}
+
+
+ )}
+
+ );
+}
+
export function CopilotStatusCard({
connection,
modelCount,
@@ -116,6 +199,8 @@ export function CopilotStatusCard({
const isHealthy = connection.status === 'ready';
const hasDetail = connection.copilotCliPath;
const checkedLabel = formatCheckedAt(connection.checkedAt);
+ const hasVersionInfo = !!connection.copilotCliVersion;
+ const hasAccountInfo = !!connection.account;
return (
@@ -131,6 +216,12 @@ export function CopilotStatusCard({
)}
+ {hasVersionInfo && (
+
+ )}
{checkedLabel && (
{checkedLabel}
)}
@@ -146,6 +237,11 @@ export function CopilotStatusCard({
+ {/* Account info (when healthy) */}
+ {isHealthy && hasAccountInfo && (
+
+ )}
+
{/* Action hint for non-ready states */}
{!isHealthy && config.actionLabel && (
@@ -154,7 +250,7 @@ export function CopilotStatusCard({
)}
- {/* CLI path (always visible when healthy, expandable otherwise) */}
+ {/* Expandable details (healthy state) */}
{isHealthy && hasDetail && (
)}
+ {hasVersionInfo && connection.copilotCliVersion!.status === 'outdated' && connection.copilotCliVersion!.latestVersion && (
+
+
Latest version
+
+ {connection.copilotCliVersion!.latestVersion}
+
+
+ )}