gambi 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,149 @@
1
+ import { cpus, platform, totalmem } from "node:os";
2
+ import { $ } from "bun";
3
+
4
+ const LSPCI_GPU_REGEX = /: (.+)$/m;
5
+ const MACOS_CHIP_REGEX = /Chip(?:set)? Model: (.+)/;
6
+ const MACOS_VRAM_REGEX = /VRAM.*?: (\d+)/;
7
+
8
+ export interface MachineSpecs {
9
+ cpu: string;
10
+ ram: number; // in GB
11
+ gpu?: string;
12
+ vram?: number; // in GB
13
+ }
14
+
15
+ interface GPUInfo {
16
+ gpu?: string;
17
+ vram?: number;
18
+ }
19
+
20
+ async function detectLinuxGPU(): Promise<GPUInfo> {
21
+ // Try nvidia-smi first (NVIDIA GPUs)
22
+ try {
23
+ const result =
24
+ await $`nvidia-smi --query-gpu=name,memory.total --format=csv,noheader,nounits`
25
+ .text()
26
+ .catch(() => null);
27
+
28
+ if (result) {
29
+ const parts = result.trim().split(", ");
30
+ const name = parts[0];
31
+ const vramMB = parts[1];
32
+ if (name && vramMB) {
33
+ return {
34
+ gpu: name,
35
+ vram: Math.round(Number.parseInt(vramMB, 10) / 1024),
36
+ };
37
+ }
38
+ }
39
+ } catch {
40
+ // nvidia-smi not available
41
+ }
42
+
43
+ // Fallback to lspci for any GPU
44
+ const lspci = await $`lspci 2>/dev/null | grep -i 'vga\\|3d\\|display'`
45
+ .text()
46
+ .catch(() => null);
47
+
48
+ if (lspci) {
49
+ const match = lspci.match(LSPCI_GPU_REGEX);
50
+ if (match?.[1]) {
51
+ return { gpu: match[1].trim() };
52
+ }
53
+ }
54
+
55
+ return {};
56
+ }
57
+
58
+ async function detectMacOSGPU(): Promise<GPUInfo> {
59
+ const result = await $`system_profiler SPDisplaysDataType 2>/dev/null`
60
+ .text()
61
+ .catch(() => null);
62
+
63
+ if (result) {
64
+ const chipMatch = result.match(MACOS_CHIP_REGEX);
65
+ const vramMatch = result.match(MACOS_VRAM_REGEX);
66
+ const vramValue = vramMatch?.[1];
67
+
68
+ return {
69
+ gpu: chipMatch?.[1]?.trim(),
70
+ vram: vramValue
71
+ ? Math.round(Number.parseInt(vramValue, 10) / 1024)
72
+ : undefined,
73
+ };
74
+ }
75
+
76
+ return {};
77
+ }
78
+
79
+ async function detectWindowsGPU(): Promise<GPUInfo> {
80
+ const result =
81
+ await $`wmic path win32_VideoController get name,adapterram /format:csv`
82
+ .text()
83
+ .catch(() => null);
84
+
85
+ if (result) {
86
+ const lines = result.trim().split("\n").filter(Boolean);
87
+ const dataLine = lines[1];
88
+ if (dataLine) {
89
+ const parts = dataLine.split(",");
90
+ const adapterRam = parts[1];
91
+ const name = parts[2];
92
+ return {
93
+ gpu: name?.trim(),
94
+ vram: adapterRam
95
+ ? Math.round(Number.parseInt(adapterRam, 10) / 1024 / 1024 / 1024)
96
+ : undefined,
97
+ };
98
+ }
99
+ }
100
+
101
+ return {};
102
+ }
103
+
104
+ async function detectGPU(): Promise<GPUInfo> {
105
+ const os = platform();
106
+
107
+ try {
108
+ if (os === "linux") {
109
+ return await detectLinuxGPU();
110
+ }
111
+ if (os === "darwin") {
112
+ return await detectMacOSGPU();
113
+ }
114
+ if (os === "win32") {
115
+ return await detectWindowsGPU();
116
+ }
117
+ } catch {
118
+ // GPU detection failed
119
+ }
120
+
121
+ return {};
122
+ }
123
+
124
+ export async function detectSpecs(): Promise<MachineSpecs> {
125
+ const cpuInfo = cpus();
126
+ const cpu = cpuInfo[0]?.model ?? "Unknown";
127
+ const ram = Math.round(totalmem() / 1024 / 1024 / 1024); // Convert to GB
128
+
129
+ const gpuInfo = await detectGPU();
130
+
131
+ return {
132
+ cpu,
133
+ ram,
134
+ ...gpuInfo,
135
+ };
136
+ }
137
+
138
+ export function formatSpecs(specs: MachineSpecs): string {
139
+ const parts = [`CPU: ${specs.cpu}`, `RAM: ${specs.ram}GB`];
140
+
141
+ if (specs.gpu) {
142
+ parts.push(`GPU: ${specs.gpu}`);
143
+ }
144
+ if (specs.vram) {
145
+ parts.push(`VRAM: ${specs.vram}GB`);
146
+ }
147
+
148
+ return parts.join(" | ");
149
+ }