feat(ui): redesign cliproxy page with master-detail layout

- Replace tab-based layout with sidebar + detail panel pattern
- Add provider navigation in left sidebar with quick actions
- Implement provider detail panel with model preferences and accounts
- Add Config Editor and Logs quick access in sidebar
- Fix naming consistency: Clipproxy → Cliproxy (single p) across 8 files
- Fix TypeScript errors for models and stats data shapes
This commit is contained in:
kaitranntt
2025-12-11 15:44:51 -05:00
parent 819a201391
commit f8648be6d9
25 changed files with 2364 additions and 198 deletions
+2 -2
View File
@@ -103,8 +103,8 @@ export {
} from './auth-handler';
// Stats fetcher
export type { ClipproxyStats } from './stats-fetcher';
export { fetchClipproxyStats, isClipproxyRunning } from './stats-fetcher';
export type { CliproxyStats } from './stats-fetcher';
export { fetchCliproxyStats, isCliproxyRunning } from './stats-fetcher';
// OpenAI compatibility layer
export type { OpenAICompatProvider, OpenAICompatModel } from './openai-compat-manager';
+4 -4
View File
@@ -8,7 +8,7 @@
import { CCS_INTERNAL_API_KEY, CLIPROXY_DEFAULT_PORT } from './config-generator';
/** Usage statistics from CLIProxyAPI */
export interface ClipproxyStats {
export interface CliproxyStats {
/** Total number of requests processed */
totalRequests: number;
/** Token counts */
@@ -59,9 +59,9 @@ interface UsageApiResponse {
* @param port CLIProxyAPI port (default: 8317)
* @returns Stats object or null if unavailable
*/
export async function fetchClipproxyStats(
export async function fetchCliproxyStats(
port: number = CLIPROXY_DEFAULT_PORT
): Promise<ClipproxyStats | null> {
): Promise<CliproxyStats | null> {
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 3000); // 3s timeout
@@ -123,7 +123,7 @@ export async function fetchClipproxyStats(
* @param port CLIProxyAPI port (default: 8317)
* @returns true if proxy is running
*/
export async function isClipproxyRunning(port: number = CLIPROXY_DEFAULT_PORT): Promise<boolean> {
export async function isCliproxyRunning(port: number = CLIPROXY_DEFAULT_PORT): Promise<boolean> {
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 1000); // 1s timeout
+5 -5
View File
@@ -12,7 +12,7 @@ import { Config, Settings } from '../types/config';
import { expandPath } from '../utils/helpers';
import { runHealthChecks, fixHealthIssue } from './health-service';
import { getAllAuthStatus, getOAuthConfig, initializeAccounts } from '../cliproxy/auth-handler';
import { fetchClipproxyStats, isClipproxyRunning } from '../cliproxy/stats-fetcher';
import { fetchCliproxyStats, isCliproxyRunning } from '../cliproxy/stats-fetcher';
import {
listOpenAICompatProviders,
getOpenAICompatProvider,
@@ -1036,12 +1036,12 @@ apiRoutes.get('/files', (_req: Request, res: Response): void => {
/**
* GET /api/cliproxy/stats - Get CLIProxyAPI usage statistics
* Returns: ClipproxyStats or error if proxy not running
* Returns: CliproxyStats or error if proxy not running
*/
apiRoutes.get('/cliproxy/stats', async (_req: Request, res: Response): Promise<void> => {
try {
// Check if proxy is running first
const running = await isClipproxyRunning();
const running = await isCliproxyRunning();
if (!running) {
res.status(503).json({
error: 'CLIProxyAPI not running',
@@ -1051,7 +1051,7 @@ apiRoutes.get('/cliproxy/stats', async (_req: Request, res: Response): Promise<v
}
// Fetch stats from management API
const stats = await fetchClipproxyStats();
const stats = await fetchCliproxyStats();
if (!stats) {
res.status(503).json({
error: 'Stats unavailable',
@@ -1072,7 +1072,7 @@ apiRoutes.get('/cliproxy/stats', async (_req: Request, res: Response): Promise<v
*/
apiRoutes.get('/cliproxy/status', async (_req: Request, res: Response): Promise<void> => {
try {
const running = await isClipproxyRunning();
const running = await isCliproxyRunning();
res.json({ running });
} catch (error) {
res.status(500).json({ error: (error as Error).message });