mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 08:17:11 +00:00
feat(cliproxy): add dashboard UI parity for version stability
Add version stability warnings to Dashboard API and UI: - Extend /api/cliproxy/update-check with isStable, maxStableVersion, stabilityMessage - Health check shows warning status for v81+ installations - UI header displays version badge with amber warning for unstable Closes: relates to #269
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
import { info, warn } from '../utils/ui';
|
||||
import { getBinDir, CLIPROXY_DEFAULT_PORT } from './config-generator';
|
||||
import { BinaryInfo, BinaryManagerConfig } from './types';
|
||||
import { CLIPROXY_FALLBACK_VERSION } from './platform-detector';
|
||||
import { CLIPROXY_FALLBACK_VERSION, CLIPROXY_MAX_STABLE_VERSION } from './platform-detector';
|
||||
import { isProxyRunning, stopProxy } from './services/proxy-lifecycle-service';
|
||||
import { waitForPortFree } from '../utils/port-utils';
|
||||
import {
|
||||
@@ -151,11 +151,29 @@ export interface CliproxyUpdateCheckResult {
|
||||
latestVersion: string;
|
||||
fromCache: boolean;
|
||||
checkedAt: number;
|
||||
// Stability fields
|
||||
isStable: boolean;
|
||||
maxStableVersion: string;
|
||||
stabilityMessage?: string;
|
||||
}
|
||||
|
||||
/** Check for CLIProxyAPI binary updates */
|
||||
export async function checkCliproxyUpdate(): Promise<CliproxyUpdateCheckResult> {
|
||||
return new BinaryManager().checkForUpdates();
|
||||
const result = await new BinaryManager().checkForUpdates();
|
||||
|
||||
// Import isNewerVersion for stability check
|
||||
const { isNewerVersion } = await import('./binary/version-checker');
|
||||
const isStable = !isNewerVersion(result.currentVersion, CLIPROXY_MAX_STABLE_VERSION);
|
||||
const stabilityMessage = isStable
|
||||
? undefined
|
||||
: `v${result.currentVersion} has known stability issues. Max stable: v${CLIPROXY_MAX_STABLE_VERSION}`;
|
||||
|
||||
return {
|
||||
...result,
|
||||
isStable,
|
||||
maxStableVersion: CLIPROXY_MAX_STABLE_VERSION,
|
||||
stabilityMessage,
|
||||
};
|
||||
}
|
||||
|
||||
// Re-export version pin functions
|
||||
|
||||
@@ -15,6 +15,8 @@ import {
|
||||
} from '../../cliproxy';
|
||||
import { getPortProcess, isCLIProxyProcess } from '../../utils/port-utils';
|
||||
import type { HealthCheck } from './types';
|
||||
import { CLIPROXY_MAX_STABLE_VERSION } from '../../cliproxy/platform-detector';
|
||||
import { isNewerVersion } from '../../cliproxy/binary/version-checker';
|
||||
|
||||
/**
|
||||
* Check CLIProxy binary installation
|
||||
@@ -23,6 +25,21 @@ export function checkCliproxyBinary(): HealthCheck {
|
||||
if (isCLIProxyInstalled()) {
|
||||
const version = getInstalledCliproxyVersion();
|
||||
const binaryPath = getCLIProxyPath();
|
||||
|
||||
// Check if version exceeds stable cap
|
||||
const isUnstable = isNewerVersion(version, CLIPROXY_MAX_STABLE_VERSION);
|
||||
|
||||
if (isUnstable) {
|
||||
return {
|
||||
id: 'cliproxy-binary',
|
||||
name: 'CLIProxy Binary',
|
||||
status: 'warning',
|
||||
message: `v${version} (unstable)`,
|
||||
details: binaryPath,
|
||||
fix: `Downgrade: ccs cliproxy install ${CLIPROXY_MAX_STABLE_VERSION.replace(/-\d+$/, '')}`,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
id: 'cliproxy-binary',
|
||||
name: 'CLIProxy Binary',
|
||||
|
||||
@@ -6,11 +6,17 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { RefreshCw, Loader2 } from 'lucide-react';
|
||||
import { RefreshCw, Loader2, AlertTriangle } from 'lucide-react';
|
||||
import { useCliproxyAuth } from '@/hooks/use-cliproxy';
|
||||
import { useCliproxyAuthFlow } from '@/hooks/use-cliproxy-auth-flow';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
interface VersionInfo {
|
||||
currentVersion: string;
|
||||
isStable: boolean;
|
||||
stabilityMessage?: string;
|
||||
}
|
||||
|
||||
interface LoginButtonProps {
|
||||
provider: string;
|
||||
displayName: string;
|
||||
@@ -110,6 +116,22 @@ export function CliproxyHeader({
|
||||
const { data: authData } = useCliproxyAuth();
|
||||
const { provider: authProvider, isAuthenticating, startAuth } = useCliproxyAuthFlow();
|
||||
const lastUpdatedText = useRelativeTime(lastUpdated);
|
||||
const [versionInfo, setVersionInfo] = useState<VersionInfo | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
fetch('/api/cliproxy/update-check')
|
||||
.then((res) => (res.ok ? res.json() : null))
|
||||
.then((data) => {
|
||||
if (data) {
|
||||
setVersionInfo({
|
||||
currentVersion: data.currentVersion,
|
||||
isStable: data.isStable,
|
||||
stabilityMessage: data.stabilityMessage,
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(() => {}); // Silently fail
|
||||
}, []);
|
||||
|
||||
const providers = [
|
||||
{ id: 'claude', displayName: 'Claude' },
|
||||
@@ -170,6 +192,21 @@ export function CliproxyHeader({
|
||||
{isRunning ? 'Running' : 'Offline'}
|
||||
</Badge>
|
||||
|
||||
{versionInfo && (
|
||||
<Badge
|
||||
variant={versionInfo.isStable ? 'secondary' : 'destructive'}
|
||||
className={cn(
|
||||
'gap-1.5',
|
||||
!versionInfo.isStable &&
|
||||
'bg-amber-500/20 text-amber-600 dark:text-amber-400 border-amber-500/30'
|
||||
)}
|
||||
title={versionInfo.stabilityMessage}
|
||||
>
|
||||
{!versionInfo.isStable && <AlertTriangle className="w-3 h-3" />}v
|
||||
{versionInfo.currentVersion}
|
||||
</Badge>
|
||||
)}
|
||||
|
||||
{lastUpdatedText && (
|
||||
<span className="text-xs text-muted-foreground">{lastUpdatedText}</span>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user