fix(quotas): unifier le décompte IA (BYOK, rollback) et combler les fuites
Centralise la réserve via ai-quota, corrige admin unavailable (-1), brancher les routes sans quota et le host-pays brainstorm, avec usage-meter élargi, noms de clusters, MCP et ajustements dashboard/insights. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -41,9 +41,16 @@ import { cn } from '@/lib/utils'
|
||||
interface McpSettingsPanelProps {
|
||||
initialKeys: McpKeyInfo[]
|
||||
serverStatus: McpServerStatus
|
||||
mcpAllowed?: boolean
|
||||
tier?: string
|
||||
}
|
||||
|
||||
export function McpSettingsPanel({ initialKeys, serverStatus }: McpSettingsPanelProps) {
|
||||
export function McpSettingsPanel({
|
||||
initialKeys,
|
||||
serverStatus,
|
||||
mcpAllowed = true,
|
||||
tier = 'PRO',
|
||||
}: McpSettingsPanelProps) {
|
||||
const [keys, setKeys] = useState<McpKeyInfo[]>(initialKeys)
|
||||
const [createOpen, setCreateOpen] = useState(false)
|
||||
const [isPending, startTransition] = useTransition()
|
||||
@@ -69,7 +76,7 @@ export function McpSettingsPanel({ initialKeys, serverStatus }: McpSettingsPanel
|
||||
...prev,
|
||||
])
|
||||
} catch (err) {
|
||||
toast.error(err instanceof Error ? err.message : 'Failed to generate key')
|
||||
toast.error(err instanceof Error ? err.message : t('mcpSettings.apiKeys.errors.generate'))
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -84,7 +91,7 @@ export function McpSettingsPanel({ initialKeys, serverStatus }: McpSettingsPanel
|
||||
)
|
||||
toast.success(t('toast.operationSuccess'))
|
||||
} catch (err) {
|
||||
toast.error(err instanceof Error ? err.message : 'Failed to revoke key')
|
||||
toast.error(err instanceof Error ? err.message : t('mcpSettings.apiKeys.errors.revoke'))
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -97,7 +104,7 @@ export function McpSettingsPanel({ initialKeys, serverStatus }: McpSettingsPanel
|
||||
setKeys(prev => prev.filter(k => k.shortId !== shortId))
|
||||
toast.success(t('toast.operationSuccess'))
|
||||
} catch (err) {
|
||||
toast.error(err instanceof Error ? err.message : 'Failed to delete key')
|
||||
toast.error(err instanceof Error ? err.message : t('mcpSettings.apiKeys.errors.delete'))
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -183,6 +190,11 @@ export function McpSettingsPanel({ initialKeys, serverStatus }: McpSettingsPanel
|
||||
<p className="text-[10px] text-concrete mt-0.5">{t('mcpSettings.apiKeys.description')}</p>
|
||||
</div>
|
||||
</div>
|
||||
{!mcpAllowed ? (
|
||||
<p className="text-[10px] text-concrete max-w-[200px] text-end leading-relaxed">
|
||||
{t('mcpSettings.tierRequired', { tier })}
|
||||
</p>
|
||||
) : (
|
||||
<Dialog open={createOpen} onOpenChange={setCreateOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<button className="flex items-center gap-1.5 px-4 py-2 rounded-xl bg-ink text-paper text-[10px] font-bold uppercase tracking-[0.15em] hover:scale-[1.02] active:scale-95 transition-all duration-300 shadow-lg shadow-ink/20">
|
||||
@@ -192,8 +204,17 @@ export function McpSettingsPanel({ initialKeys, serverStatus }: McpSettingsPanel
|
||||
</DialogTrigger>
|
||||
<CreateKeyDialog onGenerate={handleGenerate} isPending={isPending} />
|
||||
</Dialog>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{!mcpAllowed && (
|
||||
<div className="px-6 pb-4">
|
||||
<p className="text-[11px] text-amber-800 dark:text-amber-200 bg-amber-500/10 border border-amber-500/20 rounded-xl px-4 py-3 leading-relaxed">
|
||||
{t('mcpSettings.upgradeHint')}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="p-6">
|
||||
{keys.length === 0 ? (
|
||||
<div className="text-center py-8">
|
||||
|
||||
Reference in New Issue
Block a user