UNPKG

sesterce-cli

Version:

A powerful command-line interface tool for managing Sesterce Cloud services. Sesterce CLI provides easy access to GPU cloud instances, AI inference services, container registries, and SSH key management directly from your terminal.

128 lines (111 loc) 3.8 kB
import { UseCase } from "@/core/domain/use-case"; import { Either, left, right } from "@/core/logic/either"; import { ApiClientProvider } from "@/providers/api-client-provider"; import { GpuCloudInstanceOffer } from "../../domain/instance-offer"; import { GroupedGpuCloudInstanceOffer } from "../../domain/instance-offer/offer"; import { InstanceOffersFetchError } from "./errors/instance-offers-fetch-error"; const gpuPriority = ["B200", "H200", "H100", "MI300X", "A100"]; export class ListGpuCloudOffers implements UseCase<void, GroupedGpuCloudInstanceOffer[], InstanceOffersFetchError> { constructor(private readonly apiClient: ApiClientProvider) {} private initalSortOffers(offers: GpuCloudInstanceOffer[]) { return offers.sort((a, b) => { // Sort by vRAM if (b.configuration.vRamGB !== a.configuration.vRamGB) { return b.configuration.vRamGB - a.configuration.vRamGB; } // Then by number of GPUs if (b.gpuCount !== a.gpuCount) { return b.gpuCount - a.gpuCount; } const priceA = (a.gpuCount ?? 0) > 0 ? (a.hourlyPrice ?? Infinity) / (a.gpuCount || 1) : Infinity; const priceB = (b.gpuCount ?? 0) > 0 ? (b.hourlyPrice ?? Infinity) / (b.gpuCount || 1) : Infinity; // Finally by price per GPU return priceA - priceB; }); } private groupOffers( offers: GpuCloudInstanceOffer[] ): Record<string, GroupedGpuCloudInstanceOffer[]> { const groupedOffers = offers.reduce( (acc, offer) => { const key = `${offer.gpuName}-${offer.gpuCount}`; if (!acc[key]) { acc[key] = { offer, regions: [], }; } // Add regions from availability offer.availability.forEach((availability) => { if (availability.available) { if ( !acc[key].regions.some( (region) => region.region === availability.region ) ) { acc[key].regions.push({ region: availability.region, frontendName: availability.name, countryCode: availability.countryCode ?? null, }); } } }); return acc; }, {} as Record<string, GroupedGpuCloudInstanceOffer> ); // Group by GPU type return Object.values(groupedOffers).reduce( (acc, groupedOffer) => { const gpuType = groupedOffer.offer.gpuName; if (!acc[gpuType]) { acc[gpuType] = []; } acc[gpuType].push(groupedOffer); return acc; }, {} as Record<string, GroupedGpuCloudInstanceOffer[]> ); } private sortOffersByPriority( groupedOffers: Record<string, GroupedGpuCloudInstanceOffer[]> ) { const sortedGpuTypes = gpuPriority.concat( Object.keys(groupedOffers).filter( (gpuType) => !gpuPriority.includes(gpuType) ) ); return sortedGpuTypes.flatMap((gpuType) => groupedOffers[gpuType]); } async execute(): Promise< Either<InstanceOffersFetchError, GroupedGpuCloudInstanceOffer[]> > { try { const offers = await this.apiClient.request<GpuCloudInstanceOffer[]>( "/gpu-cloud/instances/offers" ); const sortedOffers = this.initalSortOffers(offers ?? []); const groupedOffers = this.groupOffers(sortedOffers); const sortedOffersByPriority = this.sortOffersByPriority(groupedOffers); return right( sortedOffersByPriority.filter((offer) => offer.regions.length) ); } catch (error) { return left( new InstanceOffersFetchError( error instanceof Error ? error.message : "Unexpected error occurred." ) ); } } }