refactor(cliproxy): address review feedback on parity and refresh flow

- make refresh ownership handling exhaustive in provider refresher

- extend backend/ui sync test to provider IDs and device-code providers

- remove DEFAULT_CURSOR_PORT re-export from use-cursor hook

- import cursor default port directly from shared defaults module
This commit is contained in:
Tam Nhu Tran
2026-02-18 03:24:28 +07:00
parent 5a786263bc
commit 39593c161b
4 changed files with 40 additions and 19 deletions
+18 -16
View File
@@ -26,6 +26,10 @@ export interface ProviderRefreshResult {
delegated?: boolean;
}
function assertNever(value: never): never {
throw new Error(`Unhandled token refresh ownership: ${String(value)}`);
}
/**
* Check if a provider's token refresh is delegated to CLIProxy
*/
@@ -47,24 +51,22 @@ export async function refreshToken(
return await refreshGeminiTokenWrapper();
}
if (isRefreshDelegated(provider)) {
// CLIProxyAPIPlus handles refresh for these providers automatically.
// No action needed from CCS — report success with delegated flag.
return { success: true, delegated: true };
}
const ownership = getTokenRefreshOwnership(provider);
if (ownership === 'unsupported') {
return {
success: false,
error: `Token refresh not yet implemented for ${provider}`,
};
switch (ownership) {
case 'cliproxy':
// CLIProxyAPIPlus handles refresh for these providers automatically.
// No action needed from CCS — report success with delegated flag.
return { success: true, delegated: true };
case 'unsupported':
case 'ccs':
// Non-gemini CCS-owned refresh paths are not implemented yet.
return {
success: false,
error: `Token refresh not yet implemented for ${provider}`,
};
default:
return assertNever(ownership);
}
return {
success: false,
error: `Unknown provider: ${provider}`,
};
}
/**
@@ -7,10 +7,22 @@
import { describe, expect, test } from 'bun:test';
import { CLIPROXY_DEFAULT_PORT as BACKEND_CLIPROXY_DEFAULT_PORT } from '../../../src/cliproxy/config/port-manager';
import { DEFAULT_CURSOR_PORT as BACKEND_CURSOR_DEFAULT_PORT } from '../../../src/cursor/cursor-models';
import {
CLIPROXY_PROVIDER_IDS as BACKEND_CLIPROXY_PROVIDER_IDS,
getProvidersByOAuthFlow,
} from '../../../src/cliproxy/provider-capabilities';
import {
CLIPROXY_DEFAULT_PORT as UI_CLIPROXY_DEFAULT_PORT,
DEFAULT_CURSOR_PORT as UI_CURSOR_DEFAULT_PORT,
} from '../../../ui/src/lib/default-ports';
import {
CLIPROXY_PROVIDERS as UI_CLIPROXY_PROVIDERS,
DEVICE_CODE_PROVIDERS as UI_DEVICE_CODE_PROVIDERS,
} from '../../../ui/src/lib/provider-config';
function sorted(values: readonly string[]): string[] {
return [...values].sort((a, b) => a.localeCompare(b));
}
describe('Default Port Sync', () => {
test('CLIProxy default port is synced between backend and UI', () => {
@@ -20,4 +32,12 @@ describe('Default Port Sync', () => {
test('Cursor default port is synced between backend and UI', () => {
expect(UI_CURSOR_DEFAULT_PORT).toBe(BACKEND_CURSOR_DEFAULT_PORT);
});
test('CLIProxy provider IDs are synced between backend and UI', () => {
expect(sorted(UI_CLIPROXY_PROVIDERS)).toEqual(sorted(BACKEND_CLIPROXY_PROVIDER_IDS));
});
test('Device code providers are synced between backend and UI', () => {
expect(sorted(UI_DEVICE_CODE_PROVIDERS)).toEqual(sorted(getProvidersByOAuthFlow('device_code')));
});
});
-2
View File
@@ -8,8 +8,6 @@ import { useMemo } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { withApiBase } from '@/lib/api-client';
export { DEFAULT_CURSOR_PORT } from '@/lib/default-ports';
export interface CursorStatus {
enabled: boolean;
authenticated: boolean;
+2 -1
View File
@@ -23,7 +23,8 @@ import {
XCircle,
} from 'lucide-react';
import { cn } from '@/lib/utils';
import { DEFAULT_CURSOR_PORT, useCursor } from '@/hooks/use-cursor';
import { useCursor } from '@/hooks/use-cursor';
import { DEFAULT_CURSOR_PORT } from '@/lib/default-ports';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';