mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-19 14:15:27 +00:00
fix(cliproxy): harden account pools per pre-merge usefulness review
- pool --enable/--disable: refuse remote targets with manual config guidance; resolve the lifecycle port instead of assuming 8317 - enablePoolRouting: roll back the pool flag when config regeneration fails; already-enabled path re-runs regeneration (repairable state) - pool opt-in prompt: gate on hasUnifiedConfig (legacy installs skip); never auto-accept consent under --yes/CCS_YES - order show (file mode): render selector pick order incl. residual on-disk priorities and surface drift instead of alphabetical order - order --reset: clear residual priority fields via management-API PATCH when proxy runs, atomic direct write when stopped - quota pool section: classify in-proxy 429 cooldowns as cooling with reset times (graceful degradation when proxy or endpoint is absent); honest paused label plus resume hint - routing state: remote targets report pool as not manageable instead of echoing the local flag; strategy/affinity apply warns when pool routing overrides the change (CLI, API message, and dashboard) - claude model-neutral: --config explicit pins survive the stale-pin migration; remote env path filters historical default pins read from claude.settings.json without mutating the file - cross-lane guard: also checks account-profile CLAUDE_CONFIG_DIR lanes for email overlap, not only the ambient ~/.claude login - onboarding hint: opt-in copy naming ccs cliproxy pool --enable - dashboard card: pool-ON shows drain-order pointer, pool-OFF shows the enable command, local-only note for remote proxies (i18n x5)
This commit is contained in:
1 parent
2b7cfa32c8
commit
1c90388b5d
25 files changed
+2489
-125
No files matched your search
@@ -87,4 +87,109 @@ describe('RoutingGuidanceCard', () => {
|
||||
).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: /session affinity unavailable/i })).toBeDisabled();
|
||||
});
|
||||
|
||||
it('compact: pool ON shows the drain-order pointer and an inline override warning', () => {
|
||||
render(
|
||||
<RoutingGuidanceCard
|
||||
compact
|
||||
state={{
|
||||
strategy: 'fill-first',
|
||||
source: 'live',
|
||||
target: 'local',
|
||||
reachable: true,
|
||||
poolRouting: { enabled: true, maxRetryCredentials: 3 },
|
||||
}}
|
||||
sessionAffinityState={{
|
||||
enabled: true,
|
||||
ttl: '1h',
|
||||
source: 'config',
|
||||
target: 'local',
|
||||
reachable: true,
|
||||
manageable: true,
|
||||
}}
|
||||
isLoading={false}
|
||||
isSaving={false}
|
||||
onApply={() => undefined}
|
||||
onApplyAffinity={() => undefined}
|
||||
/>
|
||||
);
|
||||
|
||||
// Drain-order CLI pointer is visible (not hidden behind a hover tooltip).
|
||||
expect(
|
||||
screen.getByText(/ccs cliproxy quota or ccs cliproxy accounts order/i)
|
||||
).toBeInTheDocument();
|
||||
// Max retry stays visible in the badge.
|
||||
expect(screen.getByText(/On · Max retry 3/i)).toBeInTheDocument();
|
||||
// Static override warning is rendered before the user clicks anything.
|
||||
expect(
|
||||
screen.getByText(/will not take effect until you disable it: ccs cliproxy pool --disable/i)
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('compact: pool OFF surfaces the how-to-enable command as visible text', () => {
|
||||
render(
|
||||
<RoutingGuidanceCard
|
||||
compact
|
||||
state={{
|
||||
strategy: 'round-robin',
|
||||
source: 'live',
|
||||
target: 'local',
|
||||
reachable: true,
|
||||
poolRouting: { enabled: false },
|
||||
}}
|
||||
sessionAffinityState={{
|
||||
enabled: false,
|
||||
ttl: '1h',
|
||||
source: 'config',
|
||||
target: 'local',
|
||||
reachable: true,
|
||||
manageable: true,
|
||||
}}
|
||||
isLoading={false}
|
||||
isSaving={false}
|
||||
onApply={() => undefined}
|
||||
onApplyAffinity={() => undefined}
|
||||
/>
|
||||
);
|
||||
|
||||
// The enable command is visible, not buried in a hover-only tooltip.
|
||||
expect(screen.getByText(/ccs cliproxy pool --enable/i)).toBeInTheDocument();
|
||||
// No override warning when pool is off.
|
||||
expect(screen.queryByText(/ccs cliproxy pool --disable/i)).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('compact: remote pool (manageable false) shows a local-only note, not a confident On/Off', () => {
|
||||
render(
|
||||
<RoutingGuidanceCard
|
||||
compact
|
||||
state={{
|
||||
strategy: 'round-robin',
|
||||
source: 'live',
|
||||
target: 'remote',
|
||||
reachable: true,
|
||||
poolRouting: {
|
||||
enabled: true,
|
||||
manageable: false,
|
||||
message: 'Pool routing is managed locally; this remote proxy may not reflect it.',
|
||||
},
|
||||
}}
|
||||
sessionAffinityState={{
|
||||
source: 'unsupported',
|
||||
target: 'remote',
|
||||
reachable: true,
|
||||
manageable: false,
|
||||
}}
|
||||
isLoading={false}
|
||||
isSaving={false}
|
||||
onApply={() => undefined}
|
||||
onApplyAffinity={() => undefined}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(
|
||||
screen.getByText('Pool routing is managed locally; this remote proxy may not reflect it.')
|
||||
).toBeInTheDocument();
|
||||
// No override warning for a remote proxy the local flag does not manage.
|
||||
expect(screen.queryByText(/ccs cliproxy pool --disable/i)).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user