diff --git a/src/commands/cliproxy/index.ts b/src/commands/cliproxy/index.ts index b269371b..02ae8bc5 100644 --- a/src/commands/cliproxy/index.ts +++ b/src/commands/cliproxy/index.ts @@ -39,6 +39,7 @@ import { handleRoutingExplain, handleRoutingSet, handleRoutingAffinityStatus, + handleRoutingAffinityHelp, handleRoutingAffinitySet, } from './routing-subcommand'; import { @@ -196,6 +197,10 @@ export async function handleCliproxyCommand(args: string[]): Promise { return; } if (subcommand === 'affinity') { + if (hasAnyFlag(remainingArgs.slice(2), ['--help', '-h'])) { + await handleRoutingAffinityHelp(); + return; + } if (remainingArgs[2]) { await handleRoutingAffinitySet(remainingArgs.slice(2)); return; diff --git a/src/commands/cliproxy/routing-subcommand.ts b/src/commands/cliproxy/routing-subcommand.ts index c2272597..ea63d9f2 100644 --- a/src/commands/cliproxy/routing-subcommand.ts +++ b/src/commands/cliproxy/routing-subcommand.ts @@ -170,6 +170,23 @@ export async function handleRoutingAffinityStatus(): Promise { printSessionRecognitionGuide(); } +export async function handleRoutingAffinityHelp(): Promise { + await initUI(); + console.log(''); + console.log(header('CLIProxy Session Affinity')); + console.log(''); + console.log(subheader('Usage:')); + console.log(` ${color('ccs cliproxy routing affinity', 'command')}`); + console.log(` ${color('ccs cliproxy routing affinity on', 'command')}`); + console.log(` ${color('ccs cliproxy routing affinity off', 'command')}`); + console.log(` ${color('ccs cliproxy routing affinity on --ttl 1h', 'command')}`); + console.log(''); + printSessionAffinityGuide(); + console.log(` ${dim('Accepted TTL examples: 30m, 1h, 2h30m')}`); + console.log(''); + printSessionRecognitionGuide(); +} + export async function handleRoutingAffinitySet(args: string[]): Promise { const requested = normalizeCliproxySessionAffinityEnabled(args[0]); const extractedTtl = extractOption(args.slice(1), ['--ttl']); diff --git a/ui/src/components/monitoring/proxy-status-widget.tsx b/ui/src/components/monitoring/proxy-status-widget.tsx index 0c6e1ffa..cfa026df 100644 --- a/ui/src/components/monitoring/proxy-status-widget.tsx +++ b/ui/src/components/monitoring/proxy-status-widget.tsx @@ -169,19 +169,6 @@ export function ProxyStatusWidget() { const updateSessionAffinity = useUpdateCliproxySessionAffinity(); const isSavingRoutingConfig = updateRouting.isPending || updateSessionAffinity.isPending; const routingConfigError = routingError instanceof Error ? routingError : null; - const effectiveSessionAffinityState = - sessionAffinityState ?? - (sessionAffinityError instanceof Error - ? { - source: 'unsupported' as const, - target: (routingState?.target ?? (isRemoteMode ? 'remote' : 'local')) as - | 'local' - | 'remote', - reachable: false, - manageable: false, - message: sessionAffinityError.message, - } - : undefined); const startProxy = useStartProxy(); const stopProxy = useStopProxy(); const restartProxy = useRestartProxy(); @@ -213,6 +200,19 @@ export function ProxyStatusWidget() { // Determine if remote mode is enabled const remoteConfig = cliproxyConfig?.remote; const isRemoteMode = remoteConfig?.enabled && remoteConfig?.host; + const effectiveSessionAffinityState = + sessionAffinityState ?? + (sessionAffinityError instanceof Error + ? { + source: 'unsupported' as const, + target: (routingState?.target ?? (isRemoteMode ? 'remote' : 'local')) as + | 'local' + | 'remote', + reachable: false, + manageable: false, + message: sessionAffinityError.message, + } + : undefined); const isRunning = status?.running ?? false; const isActioning =