mirror of
https://github.com/tiennm99/ccs.git
synced 2026-09-03 02:19:39 +00:00
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:
@@ -26,6 +26,10 @@ export interface ProviderRefreshResult {
|
|||||||
delegated?: boolean;
|
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
|
* Check if a provider's token refresh is delegated to CLIProxy
|
||||||
*/
|
*/
|
||||||
@@ -47,24 +51,22 @@ export async function refreshToken(
|
|||||||
return await refreshGeminiTokenWrapper();
|
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);
|
const ownership = getTokenRefreshOwnership(provider);
|
||||||
if (ownership === 'unsupported') {
|
switch (ownership) {
|
||||||
return {
|
case 'cliproxy':
|
||||||
success: false,
|
// CLIProxyAPIPlus handles refresh for these providers automatically.
|
||||||
error: `Token refresh not yet implemented for ${provider}`,
|
// 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 { describe, expect, test } from 'bun:test';
|
||||||
import { CLIPROXY_DEFAULT_PORT as BACKEND_CLIPROXY_DEFAULT_PORT } from '../../../src/cliproxy/config/port-manager';
|
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 { 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 {
|
import {
|
||||||
CLIPROXY_DEFAULT_PORT as UI_CLIPROXY_DEFAULT_PORT,
|
CLIPROXY_DEFAULT_PORT as UI_CLIPROXY_DEFAULT_PORT,
|
||||||
DEFAULT_CURSOR_PORT as UI_CURSOR_DEFAULT_PORT,
|
DEFAULT_CURSOR_PORT as UI_CURSOR_DEFAULT_PORT,
|
||||||
} from '../../../ui/src/lib/default-ports';
|
} 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', () => {
|
describe('Default Port Sync', () => {
|
||||||
test('CLIProxy default port is synced between backend and UI', () => {
|
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', () => {
|
test('Cursor default port is synced between backend and UI', () => {
|
||||||
expect(UI_CURSOR_DEFAULT_PORT).toBe(BACKEND_CURSOR_DEFAULT_PORT);
|
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')));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,8 +8,6 @@ import { useMemo } from 'react';
|
|||||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||||
import { withApiBase } from '@/lib/api-client';
|
import { withApiBase } from '@/lib/api-client';
|
||||||
|
|
||||||
export { DEFAULT_CURSOR_PORT } from '@/lib/default-ports';
|
|
||||||
|
|
||||||
export interface CursorStatus {
|
export interface CursorStatus {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
authenticated: boolean;
|
authenticated: boolean;
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ import {
|
|||||||
XCircle,
|
XCircle,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { cn } from '@/lib/utils';
|
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 { Button } from '@/components/ui/button';
|
||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
import { Label } from '@/components/ui/label';
|
import { Label } from '@/components/ui/label';
|
||||||
|
|||||||
Reference in New Issue
Block a user