idlebench 1.0.0

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.
package/dist/index.js ADDED
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import chalk from 'chalk';
4
+ import { runBenchmarkCommand } from './commands/run.js';
5
+ import { runDoctor } from './commands/doctor.js';
6
+ import { runUpload } from './commands/upload.js';
7
+ const VERSION = '1.0.0';
8
+ const program = new Command();
9
+ program
10
+ .name('idlebench')
11
+ .description('Benchmark and verify idle compute before it earns.')
12
+ .version(VERSION, '-v, --version', 'Show CLI version');
13
+ program
14
+ .command('run')
15
+ .description('Run a local benchmark and upload the report to IdleBench')
16
+ .option('--api-url <url>', 'IdleBench API URL (default: https://idlebench.com)')
17
+ .action(async (_options) => {
18
+ try {
19
+ await runBenchmarkCommand();
20
+ }
21
+ catch (err) {
22
+ console.error();
23
+ console.error(chalk.red(' ✗ Benchmark failed:'), err instanceof Error ? err.message : err);
24
+ console.error();
25
+ process.exit(1);
26
+ }
27
+ });
28
+ program
29
+ .command('doctor')
30
+ .description('Check local environment for benchmark readiness')
31
+ .option('--api-url <url>', 'IdleBench API URL to test connectivity')
32
+ .action(async (options) => {
33
+ try {
34
+ await runDoctor(options);
35
+ }
36
+ catch (err) {
37
+ console.error(chalk.red(' ✗ Doctor failed:'), err instanceof Error ? err.message : err);
38
+ process.exit(1);
39
+ }
40
+ });
41
+ program
42
+ .command('upload <path>')
43
+ .description('Upload an existing benchmark report JSON')
44
+ .option('--api-url <url>', 'IdleBench API URL (default: https://idlebench.com)')
45
+ .action(async (filePath, options) => {
46
+ try {
47
+ await runUpload(filePath, options);
48
+ }
49
+ catch (err) {
50
+ console.error(chalk.red(' ✗ Upload failed:'), err instanceof Error ? err.message : err);
51
+ process.exit(1);
52
+ }
53
+ });
54
+ program
55
+ .command('version')
56
+ .description('Show CLI version')
57
+ .action(() => {
58
+ console.log();
59
+ console.log(chalk.bold('idlebench'), chalk.dim(`v${VERSION}`));
60
+ console.log(chalk.dim('The verification layer for idle compute.'));
61
+ console.log();
62
+ });
63
+ // Default: show help if no args
64
+ if (process.argv.length <= 2) {
65
+ console.log();
66
+ console.log(chalk.bold(' IdleBench') + chalk.dim(` v${VERSION}`));
67
+ console.log(chalk.dim(' The verification layer for idle compute.'));
68
+ console.log();
69
+ console.log(chalk.dim(' Usage:'));
70
+ console.log(` ${chalk.white('npx idlebench run')} ${chalk.dim('Run benchmark and publish score')}`);
71
+ console.log(` ${chalk.white('npx idlebench doctor')} ${chalk.dim('Check environment readiness')}`);
72
+ console.log(` ${chalk.white('npx idlebench upload')} ${chalk.dim('<path> Upload saved report')}`);
73
+ console.log();
74
+ console.log(chalk.dim(' Run ') + chalk.white('idlebench --help') + chalk.dim(' for full options.'));
75
+ console.log();
76
+ process.exit(0);
77
+ }
78
+ program.parse(process.argv);
@@ -0,0 +1,7 @@
1
+ export interface BenchmarkResult {
2
+ cpuHashMs: number;
3
+ matrixMs: number;
4
+ totalMs: number;
5
+ }
6
+ export declare function runBenchmark(): Promise<BenchmarkResult>;
7
+ //# sourceMappingURL=benchmark.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"benchmark.d.ts","sourceRoot":"","sources":["../../src/lib/benchmark.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;CAChB;AAgCD,wBAAsB,YAAY,IAAI,OAAO,CAAC,eAAe,CAAC,CAY7D"}
@@ -0,0 +1,34 @@
1
+ import { createHash } from 'crypto';
2
+ function hashWorkload(iterations) {
3
+ const start = Date.now();
4
+ let hash = '';
5
+ for (let i = 0; i < iterations; i++) {
6
+ hash = createHash('sha256').update(hash + i.toString()).digest('hex');
7
+ }
8
+ return Date.now() - start;
9
+ }
10
+ function matrixMultiply(size) {
11
+ const start = Date.now();
12
+ const a = Array.from({ length: size }, (_, i) => Array.from({ length: size }, (_, j) => i * size + j));
13
+ const b = Array.from({ length: size }, (_, i) => Array.from({ length: size }, (_, j) => j * size + i));
14
+ const c = Array.from({ length: size }, () => new Array(size).fill(0));
15
+ for (let i = 0; i < size; i++) {
16
+ for (let k = 0; k < size; k++) {
17
+ for (let j = 0; j < size; j++) {
18
+ c[i][j] += a[i][k] * b[k][j];
19
+ }
20
+ }
21
+ }
22
+ return Date.now() - start;
23
+ }
24
+ export async function runBenchmark() {
25
+ // CPU hash workload (2048 iterations of SHA-256)
26
+ const cpuHashMs = hashWorkload(2048);
27
+ // Matrix multiplication 128x128
28
+ const matrixMs = matrixMultiply(128);
29
+ return {
30
+ cpuHashMs,
31
+ matrixMs,
32
+ totalMs: cpuHashMs + matrixMs,
33
+ };
34
+ }
@@ -0,0 +1,8 @@
1
+ export interface DockerInfo {
2
+ available: boolean;
3
+ version: string | null;
4
+ gpuRuntime: boolean;
5
+ gpuRuntimeError: string | null;
6
+ }
7
+ export declare function getDockerInfo(): Promise<DockerInfo>;
8
+ //# sourceMappingURL=docker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker.d.ts","sourceRoot":"","sources":["../../src/lib/docker.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,OAAO,CAAA;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,UAAU,EAAE,OAAO,CAAA;IACnB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;CAC/B;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,UAAU,CAAC,CAkDzD"}
@@ -0,0 +1,48 @@
1
+ import { execa } from 'execa';
2
+ export async function getDockerInfo() {
3
+ // Check if docker is installed
4
+ let version = null;
5
+ try {
6
+ const { stdout } = await execa('docker', ['--version'], { timeout: 6000 });
7
+ const match = stdout.match(/Docker version ([\d.]+)/);
8
+ version = match ? match[1] : stdout.trim().split('\n')[0];
9
+ }
10
+ catch {
11
+ return { available: false, version: null, gpuRuntime: false, gpuRuntimeError: 'Docker not installed' };
12
+ }
13
+ // Check docker daemon is running
14
+ try {
15
+ await execa('docker', ['info'], { timeout: 8000 });
16
+ }
17
+ catch {
18
+ return { available: false, version, gpuRuntime: false, gpuRuntimeError: 'Docker daemon not running' };
19
+ }
20
+ // Try GPU runtime
21
+ let gpuRuntime = false;
22
+ let gpuRuntimeError = null;
23
+ try {
24
+ await execa('docker', [
25
+ 'run', '--rm',
26
+ '--gpus', 'all',
27
+ 'nvidia/cuda:12.3.0-base-ubuntu22.04',
28
+ 'nvidia-smi', '-L',
29
+ ], { timeout: 60000 });
30
+ gpuRuntime = true;
31
+ }
32
+ catch (err) {
33
+ gpuRuntimeError = err instanceof Error ? err.message : 'GPU runtime test failed';
34
+ // Check if it's a known non-GPU error vs docker error
35
+ if (gpuRuntimeError.includes('could not select device driver')) {
36
+ gpuRuntimeError = 'NVIDIA container toolkit not installed';
37
+ }
38
+ else if (gpuRuntimeError.includes('Unable to find image')) {
39
+ gpuRuntimeError = 'Could not pull test image';
40
+ }
41
+ }
42
+ return {
43
+ available: true,
44
+ version,
45
+ gpuRuntime,
46
+ gpuRuntimeError,
47
+ };
48
+ }
@@ -0,0 +1,13 @@
1
+ export interface GpuInfo {
2
+ name: string | null;
3
+ vendor: string | null;
4
+ vramGb: number | null;
5
+ cudaAvailable: boolean;
6
+ cudaVersion: string | null;
7
+ driverVersion: string | null;
8
+ temperature: number | null;
9
+ utilizationPercent: number | null;
10
+ detectionMethod: string;
11
+ }
12
+ export declare function getGpuInfo(): Promise<GpuInfo>;
13
+ //# sourceMappingURL=gpu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gpu.d.ts","sourceRoot":"","sources":["../../src/lib/gpu.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,aAAa,EAAE,OAAO,CAAA;IACtB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAA;IACjC,eAAe,EAAE,MAAM,CAAA;CACxB;AAiED,wBAAsB,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC,CA0BnD"}
@@ -0,0 +1,86 @@
1
+ import { execa } from 'execa';
2
+ import si from 'systeminformation';
3
+ async function tryNvidiaSmi() {
4
+ try {
5
+ const { stdout } = await execa('nvidia-smi', [
6
+ '--query-gpu=name,memory.total,driver_version,utilization.gpu,temperature.gpu',
7
+ '--format=csv,noheader,nounits',
8
+ ], { timeout: 8000 });
9
+ const lines = stdout.trim().split('\n');
10
+ if (lines.length === 0)
11
+ return null;
12
+ const parts = lines[0].split(',').map(s => s.trim());
13
+ const [name, vramMb, driver, utilization, temperature] = parts;
14
+ // Get CUDA version from nvcc or nvidia-smi
15
+ let cudaVersion = null;
16
+ let cudaAvailable = false;
17
+ try {
18
+ const { stdout: smiOut } = await execa('nvidia-smi', [], { timeout: 5000 });
19
+ const cudaMatch = smiOut.match(/CUDA Version:\s*([\d.]+)/);
20
+ if (cudaMatch) {
21
+ cudaVersion = cudaMatch[1];
22
+ cudaAvailable = true;
23
+ }
24
+ }
25
+ catch { }
26
+ return {
27
+ name: name || null,
28
+ vendor: 'NVIDIA',
29
+ vramGb: vramMb ? Math.round((parseFloat(vramMb) / 1024) * 10) / 10 : null,
30
+ driverVersion: driver || null,
31
+ cudaAvailable,
32
+ cudaVersion,
33
+ temperature: temperature ? parseFloat(temperature) : null,
34
+ utilizationPercent: utilization ? parseFloat(utilization) : null,
35
+ detectionMethod: 'nvidia-smi',
36
+ };
37
+ }
38
+ catch {
39
+ return null;
40
+ }
41
+ }
42
+ async function trySysinformation() {
43
+ try {
44
+ const graphics = await si.graphics();
45
+ if (!graphics.controllers || graphics.controllers.length === 0)
46
+ return null;
47
+ const gpu = graphics.controllers[0];
48
+ if (!gpu.model)
49
+ return null;
50
+ const isNvidia = gpu.vendor?.toLowerCase().includes('nvidia') || gpu.model?.toLowerCase().includes('nvidia');
51
+ return {
52
+ name: gpu.model,
53
+ vendor: gpu.vendor || (isNvidia ? 'NVIDIA' : null),
54
+ vramGb: gpu.vram ? Math.round((gpu.vram / 1024) * 10) / 10 : null,
55
+ cudaAvailable: isNvidia ? undefined : false,
56
+ detectionMethod: 'systeminformation',
57
+ };
58
+ }
59
+ catch {
60
+ return null;
61
+ }
62
+ }
63
+ export async function getGpuInfo() {
64
+ const defaults = {
65
+ name: null,
66
+ vendor: null,
67
+ vramGb: null,
68
+ cudaAvailable: false,
69
+ cudaVersion: null,
70
+ driverVersion: null,
71
+ temperature: null,
72
+ utilizationPercent: null,
73
+ detectionMethod: 'none',
74
+ };
75
+ // Try nvidia-smi first (most accurate for NVIDIA)
76
+ const nvidiaSmi = await tryNvidiaSmi();
77
+ if (nvidiaSmi && nvidiaSmi.name) {
78
+ return { ...defaults, ...nvidiaSmi };
79
+ }
80
+ // Fallback to systeminformation
81
+ const siGpu = await trySysinformation();
82
+ if (siGpu && siGpu.name) {
83
+ return { ...defaults, ...siGpu };
84
+ }
85
+ return defaults;
86
+ }
@@ -0,0 +1,9 @@
1
+ export interface NetworkInfo {
2
+ latencyMs: number | null;
3
+ downloadMbps: number | null;
4
+ uploadMbps: number | null;
5
+ }
6
+ export declare function measureLatency(url: string): Promise<number | null>;
7
+ export declare function estimateDownload(): Promise<number | null>;
8
+ export declare function getNetworkInfo(apiUrl: string): Promise<NetworkInfo>;
9
+ //# sourceMappingURL=network.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../src/lib/network.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA+BxE;AAED,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAc/D;AAED,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAWzE"}
@@ -0,0 +1,62 @@
1
+ import { fetch } from 'undici';
2
+ export async function measureLatency(url) {
3
+ const samples = [];
4
+ const attempts = 3;
5
+ for (let i = 0; i < attempts; i++) {
6
+ const start = Date.now();
7
+ try {
8
+ await fetch(`${url}/api/health/check`, {
9
+ method: 'GET',
10
+ signal: AbortSignal.timeout(5000),
11
+ });
12
+ samples.push(Date.now() - start);
13
+ }
14
+ catch {
15
+ // Try a fallback HEAD request
16
+ try {
17
+ const fallbackStart = Date.now();
18
+ await fetch(url, {
19
+ method: 'HEAD',
20
+ signal: AbortSignal.timeout(5000),
21
+ });
22
+ samples.push(Date.now() - fallbackStart);
23
+ }
24
+ catch { }
25
+ }
26
+ // Small delay between samples
27
+ if (i < attempts - 1)
28
+ await new Promise(r => setTimeout(r, 200));
29
+ }
30
+ if (samples.length === 0)
31
+ return null;
32
+ // Use median
33
+ samples.sort((a, b) => a - b);
34
+ return samples[Math.floor(samples.length / 2)];
35
+ }
36
+ export async function estimateDownload() {
37
+ // Download a small fixed payload and estimate throughput
38
+ const url = 'https://httpbin.org/bytes/524288'; // 512 KB
39
+ const start = Date.now();
40
+ try {
41
+ const res = await fetch(url, { signal: AbortSignal.timeout(10000) });
42
+ const buffer = await res.arrayBuffer();
43
+ const elapsed = (Date.now() - start) / 1000;
44
+ const bytes = buffer.byteLength;
45
+ const mbps = (bytes * 8) / (elapsed * 1_000_000);
46
+ return Math.round(mbps * 10) / 10;
47
+ }
48
+ catch {
49
+ return null;
50
+ }
51
+ }
52
+ export async function getNetworkInfo(apiUrl) {
53
+ const [latencyMs, downloadMbps] = await Promise.all([
54
+ measureLatency(apiUrl),
55
+ estimateDownload(),
56
+ ]);
57
+ return {
58
+ latencyMs,
59
+ downloadMbps,
60
+ uploadMbps: null, // upload test not implemented in v1 to avoid large payloads
61
+ };
62
+ }
@@ -0,0 +1,76 @@
1
+ import type { SystemInfo } from './system.js';
2
+ import type { GpuInfo } from './gpu.js';
3
+ import type { DockerInfo } from './docker.js';
4
+ import type { NetworkInfo } from './network.js';
5
+ export interface ReportData {
6
+ reportVersion: string;
7
+ providerWallet: string;
8
+ resourceName: string;
9
+ resourceType: string;
10
+ idleGatewayUrl: string | null;
11
+ system: SystemInfo;
12
+ gpu: GpuInfo;
13
+ docker: DockerInfo;
14
+ network: NetworkInfo;
15
+ scores: {
16
+ gpuScore: number;
17
+ runtimeScore: number;
18
+ networkScore: number;
19
+ inferenceScore: number;
20
+ stabilityScore: number;
21
+ finalScore: number;
22
+ grade: string;
23
+ };
24
+ benchmarkMs: number;
25
+ cliVersion: string;
26
+ }
27
+ export interface FullReport {
28
+ reportVersion: string;
29
+ providerWallet: string;
30
+ resourceName: string;
31
+ resourceType: string;
32
+ idleGatewayUrl: string | null;
33
+ system: {
34
+ os: string;
35
+ arch: string;
36
+ cpuModel: string;
37
+ cpuCores: number;
38
+ ramGb: number;
39
+ };
40
+ gpu: {
41
+ name: string | null;
42
+ vendor: string | null;
43
+ vramGb: number | null;
44
+ cudaAvailable: boolean;
45
+ cudaVersion: string | null;
46
+ driverVersion: string | null;
47
+ };
48
+ runtime: {
49
+ dockerAvailable: boolean;
50
+ dockerVersion: string | null;
51
+ dockerGpuRuntime: boolean;
52
+ };
53
+ network: {
54
+ latencyMs: number | null;
55
+ downloadMbps: number | null;
56
+ uploadMbps: number | null;
57
+ };
58
+ scores: {
59
+ gpuScore: number;
60
+ runtimeScore: number;
61
+ networkScore: number;
62
+ inferenceScore: number;
63
+ stabilityScore: number;
64
+ finalScore: number;
65
+ grade: string;
66
+ };
67
+ metadata: {
68
+ createdAt: string;
69
+ cliVersion: string;
70
+ benchmarkMs: number;
71
+ };
72
+ reportHash: string;
73
+ }
74
+ export declare function buildReport(data: ReportData): FullReport;
75
+ export declare function saveReportLocally(report: FullReport): string;
76
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/lib/report.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AACvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE/C,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,MAAM,CAAA;IACrB,cAAc,EAAE,MAAM,CAAA;IACtB,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,MAAM,EAAE,UAAU,CAAA;IAClB,GAAG,EAAE,OAAO,CAAA;IACZ,MAAM,EAAE,UAAU,CAAA;IAClB,OAAO,EAAE,WAAW,CAAA;IACpB,MAAM,EAAE;QACN,QAAQ,EAAE,MAAM,CAAA;QAChB,YAAY,EAAE,MAAM,CAAA;QACpB,YAAY,EAAE,MAAM,CAAA;QACpB,cAAc,EAAE,MAAM,CAAA;QACtB,cAAc,EAAE,MAAM,CAAA;QACtB,UAAU,EAAE,MAAM,CAAA;QAClB,KAAK,EAAE,MAAM,CAAA;KACd,CAAA;IACD,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,MAAM,CAAA;IACrB,cAAc,EAAE,MAAM,CAAA;IACtB,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,MAAM,EAAE;QACN,EAAE,EAAE,MAAM,CAAA;QACV,IAAI,EAAE,MAAM,CAAA;QACZ,QAAQ,EAAE,MAAM,CAAA;QAChB,QAAQ,EAAE,MAAM,CAAA;QAChB,KAAK,EAAE,MAAM,CAAA;KACd,CAAA;IACD,GAAG,EAAE;QACH,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;QACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;QACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;QACrB,aAAa,EAAE,OAAO,CAAA;QACtB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;QAC1B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;KAC7B,CAAA;IACD,OAAO,EAAE;QACP,eAAe,EAAE,OAAO,CAAA;QACxB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;QAC5B,gBAAgB,EAAE,OAAO,CAAA;KAC1B,CAAA;IACD,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;QACxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;QAC3B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;KAC1B,CAAA;IACD,MAAM,EAAE;QACN,QAAQ,EAAE,MAAM,CAAA;QAChB,YAAY,EAAE,MAAM,CAAA;QACpB,YAAY,EAAE,MAAM,CAAA;QACpB,cAAc,EAAE,MAAM,CAAA;QACtB,cAAc,EAAE,MAAM,CAAA;QACtB,UAAU,EAAE,MAAM,CAAA;QAClB,KAAK,EAAE,MAAM,CAAA;KACd,CAAA;IACD,QAAQ,EAAE;QACR,SAAS,EAAE,MAAM,CAAA;QACjB,UAAU,EAAE,MAAM,CAAA;QAClB,WAAW,EAAE,MAAM,CAAA;KACpB,CAAA;IACD,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,CA6CxD;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAK5D"}
@@ -0,0 +1,53 @@
1
+ import { createHash } from 'crypto';
2
+ import { writeFileSync } from 'fs';
3
+ import { join } from 'path';
4
+ export function buildReport(data) {
5
+ const reportBody = {
6
+ reportVersion: data.reportVersion,
7
+ providerWallet: data.providerWallet,
8
+ resourceName: data.resourceName,
9
+ resourceType: data.resourceType,
10
+ idleGatewayUrl: data.idleGatewayUrl,
11
+ system: {
12
+ os: data.system.os,
13
+ arch: data.system.arch,
14
+ cpuModel: data.system.cpuModel,
15
+ cpuCores: data.system.cpuCores,
16
+ ramGb: data.system.ramGb,
17
+ },
18
+ gpu: {
19
+ name: data.gpu.name,
20
+ vendor: data.gpu.vendor,
21
+ vramGb: data.gpu.vramGb,
22
+ cudaAvailable: data.gpu.cudaAvailable,
23
+ cudaVersion: data.gpu.cudaVersion,
24
+ driverVersion: data.gpu.driverVersion,
25
+ },
26
+ runtime: {
27
+ dockerAvailable: data.docker.available,
28
+ dockerVersion: data.docker.version,
29
+ dockerGpuRuntime: data.docker.gpuRuntime,
30
+ },
31
+ network: {
32
+ latencyMs: data.network.latencyMs,
33
+ downloadMbps: data.network.downloadMbps,
34
+ uploadMbps: data.network.uploadMbps,
35
+ },
36
+ scores: data.scores,
37
+ metadata: {
38
+ createdAt: new Date().toISOString(),
39
+ cliVersion: data.cliVersion,
40
+ benchmarkMs: data.benchmarkMs,
41
+ },
42
+ };
43
+ const reportHash = createHash('sha256')
44
+ .update(JSON.stringify(reportBody))
45
+ .digest('hex');
46
+ return { ...reportBody, reportHash };
47
+ }
48
+ export function saveReportLocally(report) {
49
+ const filename = `idlebench-report-${Date.now()}.json`;
50
+ const filepath = join(process.cwd(), filename);
51
+ writeFileSync(filepath, JSON.stringify(report, null, 2));
52
+ return filepath;
53
+ }
@@ -0,0 +1,24 @@
1
+ export interface ScoreInputs {
2
+ gpuName?: string | null;
3
+ vramGb?: number | null;
4
+ cpuCores: number;
5
+ ramGb: number;
6
+ cudaAvailable: boolean;
7
+ dockerAvailable: boolean;
8
+ dockerGpuRuntime: boolean;
9
+ networkLatencyMs?: number | null;
10
+ }
11
+ export declare function calculateGpuScore(inputs: ScoreInputs): number;
12
+ export declare function calculateRuntimeScore(inputs: ScoreInputs): number;
13
+ export declare function calculateNetworkScore(latencyMs?: number | null): number;
14
+ export declare function calculateInferenceScore(cpuCores: number, ramGb: number, benchmarkMs: number, gpuName?: string | null): number;
15
+ export declare function calculateStabilityScore(cpuCores: number, ramGb: number): number;
16
+ export declare function calculateFinalScore(scores: {
17
+ gpuScore: number;
18
+ runtimeScore: number;
19
+ networkScore: number;
20
+ inferenceScore: number;
21
+ stabilityScore: number;
22
+ }): number;
23
+ export declare function getGrade(score: number): string;
24
+ //# sourceMappingURL=scoring.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scoring.d.ts","sourceRoot":"","sources":["../../src/lib/scoring.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,aAAa,EAAE,OAAO,CAAA;IACtB,eAAe,EAAE,OAAO,CAAA;IACxB,gBAAgB,EAAE,OAAO,CAAA;IACzB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACjC;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAiC7D;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAMjE;AAED,wBAAgB,qBAAqB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAUvE;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAS7H;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAQ/E;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAC1C,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,cAAc,EAAE,MAAM,CAAA;IACtB,cAAc,EAAE,MAAM,CAAA;CACvB,GAAG,MAAM,CAST;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAM9C"}
@@ -0,0 +1,125 @@
1
+ export function calculateGpuScore(inputs) {
2
+ let score = 30;
3
+ if (inputs.gpuName) {
4
+ const g = inputs.gpuName.toLowerCase();
5
+ if (g.includes('h100'))
6
+ score = 100;
7
+ else if (g.includes('a100'))
8
+ score = 99;
9
+ else if (g.includes('4090'))
10
+ score = 97;
11
+ else if (g.includes('4080'))
12
+ score = 92;
13
+ else if (g.includes('3090'))
14
+ score = 88;
15
+ else if (g.includes('4070'))
16
+ score = 82;
17
+ else if (g.includes('3080'))
18
+ score = 80;
19
+ else if (g.includes('a6000'))
20
+ score = 86;
21
+ else if (g.includes('v100'))
22
+ score = 82;
23
+ else if (g.includes('3070'))
24
+ score = 72;
25
+ else if (g.includes('t4'))
26
+ score = 68;
27
+ else if (g.includes('2080'))
28
+ score = 68;
29
+ else if (g.includes('1080'))
30
+ score = 55;
31
+ else if (g.includes('amd') || g.includes('radeon') || g.includes('rx'))
32
+ score = 52;
33
+ else
34
+ score = 50;
35
+ }
36
+ else {
37
+ const coreScore = Math.min(40, (inputs.cpuCores / 64) * 40);
38
+ const ramScore = Math.min(15, (inputs.ramGb / 256) * 15);
39
+ score = Math.round(coreScore + ramScore);
40
+ }
41
+ if (inputs.vramGb) {
42
+ if (inputs.vramGb >= 40)
43
+ score = Math.min(100, score + 3);
44
+ else if (inputs.vramGb >= 24)
45
+ score = Math.min(100, score + 2);
46
+ else if (inputs.vramGb >= 16)
47
+ score = Math.min(100, score + 1);
48
+ }
49
+ return Math.max(0, Math.min(100, Math.round(score)));
50
+ }
51
+ export function calculateRuntimeScore(inputs) {
52
+ let score = 20;
53
+ if (inputs.dockerAvailable)
54
+ score += 40;
55
+ if (inputs.cudaAvailable)
56
+ score += 25;
57
+ if (inputs.dockerGpuRuntime)
58
+ score += 15;
59
+ return Math.min(100, score);
60
+ }
61
+ export function calculateNetworkScore(latencyMs) {
62
+ if (!latencyMs || latencyMs <= 0)
63
+ return 40;
64
+ if (latencyMs < 20)
65
+ return 100;
66
+ if (latencyMs < 50)
67
+ return 92;
68
+ if (latencyMs < 100)
69
+ return 82;
70
+ if (latencyMs < 150)
71
+ return 72;
72
+ if (latencyMs < 200)
73
+ return 60;
74
+ if (latencyMs < 400)
75
+ return 45;
76
+ if (latencyMs < 600)
77
+ return 30;
78
+ return 15;
79
+ }
80
+ export function calculateInferenceScore(cpuCores, ramGb, benchmarkMs, gpuName) {
81
+ let base = 50;
82
+ if (gpuName)
83
+ base += 20;
84
+ base += Math.min(15, cpuCores / 3);
85
+ base += Math.min(10, ramGb / 32);
86
+ // Faster benchmark = better score
87
+ if (benchmarkMs < 200)
88
+ base += 5;
89
+ else if (benchmarkMs > 2000)
90
+ base -= 10;
91
+ return Math.min(100, Math.max(0, Math.round(base)));
92
+ }
93
+ export function calculateStabilityScore(cpuCores, ramGb) {
94
+ let score = 75;
95
+ if (cpuCores >= 8)
96
+ score += 5;
97
+ if (cpuCores >= 16)
98
+ score += 5;
99
+ if (ramGb >= 16)
100
+ score += 5;
101
+ if (ramGb >= 32)
102
+ score += 5;
103
+ if (ramGb >= 64)
104
+ score += 5;
105
+ return Math.min(100, score);
106
+ }
107
+ export function calculateFinalScore(scores) {
108
+ const final = scores.gpuScore * 0.3 +
109
+ scores.runtimeScore * 0.2 +
110
+ scores.inferenceScore * 0.2 +
111
+ scores.networkScore * 0.15 +
112
+ scores.stabilityScore * 0.15;
113
+ return Math.max(0, Math.min(100, Math.round(final)));
114
+ }
115
+ export function getGrade(score) {
116
+ if (score >= 95)
117
+ return 'Elite';
118
+ if (score >= 85)
119
+ return 'Verified A';
120
+ if (score >= 70)
121
+ return 'Verified B';
122
+ if (score >= 55)
123
+ return 'Risky';
124
+ return 'Not Recommended';
125
+ }
@@ -0,0 +1,10 @@
1
+ export interface SystemInfo {
2
+ os: string;
3
+ arch: string;
4
+ cpuModel: string;
5
+ cpuCores: number;
6
+ ramGb: number;
7
+ platform: string;
8
+ }
9
+ export declare function getSystemInfo(): Promise<SystemInfo>;
10
+ //# sourceMappingURL=system.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system.d.ts","sourceRoot":"","sources":["../../src/lib/system.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,UAAU,CAAC,CAmBzD"}