mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-15 04:18:19 +00:00
fix(cliproxy): use backend-specific GitHub repos for version fetching
Root cause: fetchLatestVersion and fetchAllVersions were hardcoded to
CLIProxyAPIPlus repo, ignoring backend selection.
Changes:
- Add getGitHubApiUrls(backend) helper to types.ts
- Make fetchLatestVersion and fetchAllVersions backend-aware
- Make version list cache backend-specific (bin/{backend}/.version-list-cache.json)
- Update /api/cliproxy/versions route to use configured backend
- Allow version management even when proxy not running (ProxyStatusWidget)
- Show settings button in all states for easier access
This commit is contained in:
1 parent
498175e9fb
commit
0a1cbcc612
5 files changed
+149
-111
No files matched your search
@@ -289,7 +289,7 @@ export function ProxyStatusWidget() {
|
||||
<span className="text-sm font-medium">{updateCheck?.backendLabel ?? 'CLIProxy'}</span>
|
||||
</div>
|
||||
|
||||
{/* Right side: icon buttons when running */}
|
||||
{/* Right side: icon buttons */}
|
||||
<div className="flex items-center gap-1">
|
||||
{isLoading ? (
|
||||
<RefreshCw className="w-3 h-3 animate-spin text-muted-foreground" />
|
||||
@@ -310,16 +310,15 @@ export function ProxyStatusWidget() {
|
||||
isPending={stopProxy.isPending}
|
||||
variant="destructive-ghost"
|
||||
/>
|
||||
<IconButton
|
||||
icon={isExpanded ? X : Settings}
|
||||
tooltip={isExpanded ? 'Close' : 'Version settings'}
|
||||
onClick={() => setIsExpanded(!isExpanded)}
|
||||
className={isExpanded ? 'bg-muted' : undefined}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<Power className="w-3 h-3 text-muted-foreground" />
|
||||
)}
|
||||
) : null}
|
||||
{/* Settings button always visible */}
|
||||
<IconButton
|
||||
icon={isExpanded ? X : Settings}
|
||||
tooltip={isExpanded ? 'Close' : 'Version settings'}
|
||||
onClick={() => setIsExpanded(!isExpanded)}
|
||||
className={isExpanded ? 'bg-muted' : undefined}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -376,82 +375,80 @@ export function ProxyStatusWidget() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Expanded section: Version Management */}
|
||||
{isRunning && (
|
||||
<Collapsible open={isExpanded} onOpenChange={setIsExpanded}>
|
||||
<CollapsibleContent className="mt-3 pt-3 border-t border-muted">
|
||||
{/* Section header */}
|
||||
<h4 className="text-xs font-medium text-muted-foreground mb-3">Version Management</h4>
|
||||
{/* Expanded section: Version Management (available even when not running) */}
|
||||
<Collapsible open={isExpanded} onOpenChange={setIsExpanded}>
|
||||
<CollapsibleContent className="mt-3 pt-3 border-t border-muted">
|
||||
{/* Section header */}
|
||||
<h4 className="text-xs font-medium text-muted-foreground mb-3">Version Management</h4>
|
||||
|
||||
{/* Version picker row */}
|
||||
<div className="flex items-center gap-2">
|
||||
{/* Dropdown - full width, no truncation */}
|
||||
<Select
|
||||
value={selectedVersion}
|
||||
onValueChange={setSelectedVersion}
|
||||
disabled={versionsLoading}
|
||||
>
|
||||
<SelectTrigger className="h-8 text-xs flex-1">
|
||||
<SelectValue placeholder="Select version to install..." />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{versionsData?.versions.slice(0, 20).map((v) => {
|
||||
const vIsUnstable =
|
||||
versionsData?.maxStableVersion &&
|
||||
isNewerVersionClient(v, versionsData.maxStableVersion);
|
||||
return (
|
||||
<SelectItem key={v} value={v} className="text-xs">
|
||||
<span className="flex items-center gap-2">
|
||||
v{v}
|
||||
{v === versionsData.latestStable && (
|
||||
<span className="text-green-600 dark:text-green-400">(stable)</span>
|
||||
)}
|
||||
{vIsUnstable && (
|
||||
<span className="text-amber-600 dark:text-amber-400">⚠</span>
|
||||
)}
|
||||
</span>
|
||||
</SelectItem>
|
||||
);
|
||||
})}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{/* Version picker row */}
|
||||
<div className="flex items-center gap-2">
|
||||
{/* Dropdown - full width, no truncation */}
|
||||
<Select
|
||||
value={selectedVersion}
|
||||
onValueChange={setSelectedVersion}
|
||||
disabled={versionsLoading}
|
||||
>
|
||||
<SelectTrigger className="h-8 text-xs flex-1">
|
||||
<SelectValue placeholder="Select version to install..." />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{versionsData?.versions.slice(0, 20).map((v) => {
|
||||
const vIsUnstable =
|
||||
versionsData?.maxStableVersion &&
|
||||
isNewerVersionClient(v, versionsData.maxStableVersion);
|
||||
return (
|
||||
<SelectItem key={v} value={v} className="text-xs">
|
||||
<span className="flex items-center gap-2">
|
||||
v{v}
|
||||
{v === versionsData.latestStable && (
|
||||
<span className="text-green-600 dark:text-green-400">(stable)</span>
|
||||
)}
|
||||
{vIsUnstable && (
|
||||
<span className="text-amber-600 dark:text-amber-400">⚠</span>
|
||||
)}
|
||||
</span>
|
||||
</SelectItem>
|
||||
);
|
||||
})}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
{/* Install button */}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="h-8 text-xs gap-1.5 px-3"
|
||||
onClick={() => handleInstallVersion(selectedVersion)}
|
||||
disabled={installVersion.isPending || !selectedVersion}
|
||||
>
|
||||
{installVersion.isPending ? (
|
||||
<RefreshCw className="w-3.5 h-3.5 animate-spin" />
|
||||
) : (
|
||||
<Download className="w-3.5 h-3.5" />
|
||||
)}
|
||||
Install
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Stability warning for selected version */}
|
||||
{selectedVersion &&
|
||||
versionsData?.maxStableVersion &&
|
||||
isNewerVersionClient(selectedVersion, versionsData.maxStableVersion) && (
|
||||
<div className="mt-2 flex items-center gap-1.5 text-[11px] text-amber-600 dark:text-amber-400">
|
||||
<AlertTriangle className="w-3.5 h-3.5 flex-shrink-0" />
|
||||
<span>Versions above {versionsData.maxStableVersion} have known issues</span>
|
||||
</div>
|
||||
{/* Install button */}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="h-8 text-xs gap-1.5 px-3"
|
||||
onClick={() => handleInstallVersion(selectedVersion)}
|
||||
disabled={installVersion.isPending || !selectedVersion}
|
||||
>
|
||||
{installVersion.isPending ? (
|
||||
<RefreshCw className="w-3.5 h-3.5 animate-spin" />
|
||||
) : (
|
||||
<Download className="w-3.5 h-3.5" />
|
||||
)}
|
||||
Install
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Sync time */}
|
||||
{updateCheck?.checkedAt && (
|
||||
<div className="mt-2 text-[10px] text-muted-foreground/60">
|
||||
Last checked {formatTimeAgo(updateCheck.checkedAt)}
|
||||
{/* Stability warning for selected version */}
|
||||
{selectedVersion &&
|
||||
versionsData?.maxStableVersion &&
|
||||
isNewerVersionClient(selectedVersion, versionsData.maxStableVersion) && (
|
||||
<div className="mt-2 flex items-center gap-1.5 text-[11px] text-amber-600 dark:text-amber-400">
|
||||
<AlertTriangle className="w-3.5 h-3.5 flex-shrink-0" />
|
||||
<span>Versions above {versionsData.maxStableVersion} have known issues</span>
|
||||
</div>
|
||||
)}
|
||||
</CollapsibleContent>
|
||||
</Collapsible>
|
||||
)}
|
||||
|
||||
{/* Sync time */}
|
||||
{updateCheck?.checkedAt && (
|
||||
<div className="mt-2 text-[10px] text-muted-foreground/60">
|
||||
Last checked {formatTimeAgo(updateCheck.checkedAt)}
|
||||
</div>
|
||||
)}
|
||||
</CollapsibleContent>
|
||||
</Collapsible>
|
||||
|
||||
{/* Not running state */}
|
||||
{!isRunning && (
|
||||
|
||||
Reference in new issue
Block a user