@localmode/bench 0.2.0 → 0.3.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.d.ts CHANGED
@@ -199,6 +199,14 @@ interface BrowserInfo {
199
199
  brand: string;
200
200
  version: string;
201
201
  }>;
202
+ /** Rendering engine, derived from the UA (Blink / Gecko / WebKit). */
203
+ engine?: 'Blink' | 'Gecko' | 'WebKit' | 'unknown';
204
+ /** `navigator.vendor` (e.g. "Google Inc.", "Apple Computer, Inc."). */
205
+ vendor?: string;
206
+ /** `navigator.webdriver` — true under browser automation. */
207
+ webdriver?: boolean;
208
+ /** `navigator.pdfViewerEnabled`, a cheap headless/kiosk signal. */
209
+ pdfViewerEnabled?: boolean;
202
210
  }
203
211
  /** OS identification. Version is 'unknown-frozen' on engines with frozen UAs. */
204
212
  interface OSInfo {
@@ -206,7 +214,30 @@ interface OSInfo {
206
214
  version: string;
207
215
  architecture?: string;
208
216
  bitness?: string;
217
+ /** Device model from UA-CH (Android only; empty elsewhere by spec). */
209
218
  model?: string;
219
+ /** Whether the OS is running in a WoW64-style emulation layer (UA-CH `wow64`). */
220
+ wow64?: boolean;
221
+ /** `navigator.platform` (legacy, frozen but still informative: "MacIntel", "Win32", "iPhone"). */
222
+ navigatorPlatform?: string;
223
+ }
224
+ /** Form-factor classification, derived from UA-CH form factors, the UA, and touch. */
225
+ type DeviceType = 'phone' | 'tablet' | 'desktop' | 'xr' | 'tv' | 'unknown';
226
+ /** Device / form-factor signals. */
227
+ interface DeviceInfo {
228
+ type: DeviceType;
229
+ /** UA-CH `mobile` bit (Chromium) or a UA-derived guess elsewhere. */
230
+ mobile: boolean;
231
+ /** UA-CH `formFactors` (Chromium 125+): Desktop / Mobile / Tablet / XR / EInk / Watch / Automotive. */
232
+ formFactors?: string[];
233
+ /** `navigator.maxTouchPoints`. */
234
+ maxTouchPoints: number;
235
+ /** `(pointer: coarse)` media query — primary input is a touch surface. */
236
+ pointerCoarse?: boolean;
237
+ /** `(hover: none)` media query — no hover-capable primary input. */
238
+ hoverNone?: boolean;
239
+ /** Standalone / fullscreen display mode (installed PWA or kiosk). */
240
+ displayMode?: string;
210
241
  }
211
242
  /** WebGPU adapter identity + selected limits (all fields may be empty strings). */
212
243
  interface GPUInfo {
@@ -215,11 +246,155 @@ interface GPUInfo {
215
246
  architecture?: string;
216
247
  device?: string;
217
248
  description?: string;
249
+ /** Adapter-reported subgroup sizes (Chromium 130+ `info.subgroupMinSize/MaxSize`). */
250
+ subgroupMinSize?: number;
251
+ subgroupMaxSize?: number;
218
252
  isFallbackAdapter?: boolean;
219
253
  features?: string[];
220
254
  limits?: Record<string, number>;
255
+ /** `navigator.gpu.getPreferredCanvasFormat()`. */
256
+ preferredCanvasFormat?: string;
257
+ /** WGSL language features the implementation reports (`navigator.gpu.wgslLanguageFeatures`). */
258
+ wgslLanguageFeatures?: string[];
259
+ }
260
+ /** WebGL identity + capacity signals (a second, older GPU identity channel). */
261
+ interface WebGLInfo {
262
+ /** Best context available: 'webgl2', 'webgl', or null when neither creates. */
263
+ contextKind: 'webgl2' | 'webgl' | null;
264
+ /** UNMASKED_VENDOR_WEBGL when the debug extension exists, else VENDOR. */
265
+ vendor?: string;
266
+ /** UNMASKED_RENDERER_WEBGL when the debug extension exists, else RENDERER. */
267
+ renderer?: string;
268
+ version?: string;
269
+ shadingLanguageVersion?: string;
270
+ maxTextureSize?: number;
271
+ maxRenderbufferSize?: number;
272
+ maxVertexUniformVectors?: number;
273
+ maxFragmentUniformVectors?: number;
274
+ /** Number of extensions exposed (identity signal without shipping the whole list). */
275
+ extensionCount?: number;
276
+ /** Whether the renderer string names a software rasterizer (SwiftShader, llvmpipe, ...). */
277
+ softwareRenderer?: boolean;
278
+ }
279
+ /**
280
+ * WebAssembly proposal support, each probed by validating a canonical module
281
+ * (the same byte sequences `wasm-feature-detect` uses). Missing keys mean the
282
+ * probe itself failed, not that the feature is absent.
283
+ */
284
+ interface WasmFeatureSupport {
285
+ simd: boolean;
286
+ relaxedSimd: boolean;
287
+ threads: boolean;
288
+ bulkMemory: boolean;
289
+ exceptions: boolean;
290
+ /** Exception handling with `exnref` (the newer, standardized form). */
291
+ exceptionsFinal: boolean;
292
+ extendedConst: boolean;
293
+ gc: boolean;
294
+ memory64: boolean;
295
+ multiMemory: boolean;
296
+ multiValue: boolean;
297
+ mutableGlobals: boolean;
298
+ referenceTypes: boolean;
299
+ saturatedFloatToInt: boolean;
300
+ signExtensions: boolean;
301
+ tailCall: boolean;
302
+ typedFunctionReferences: boolean;
303
+ /** 128-bit wide arithmetic (`i64.add128` family). */
304
+ wideArithmetic: boolean;
305
+ /** JavaScript Promise Integration (`WebAssembly.Suspending`). */
306
+ jspi: boolean;
307
+ /** Type reflection (`WebAssembly.Function`). */
308
+ typeReflection: boolean;
309
+ /** `WebAssembly.compileStreaming` exists. */
310
+ streamingCompilation: boolean;
311
+ /** JS String Builtins (`js-string` import module), probed via the imports/builtins option. */
312
+ jsStringBuiltins: boolean;
313
+ /** Type-level `WebAssembly.Memory` growth limit reachable in this engine (pages of 64 KiB). */
314
+ maxMemoryPages?: number;
315
+ }
316
+ /**
317
+ * Availability of the browser APIs the runtimes and the paper care about.
318
+ * Each entry is a plain presence check (the feature exists on this page),
319
+ * not a functional test. Chrome Built-in AI is reported by its
320
+ * `availability()` string where the API exists.
321
+ */
322
+ interface APIAvailability {
323
+ webgpu: boolean;
324
+ webgl2: boolean;
325
+ webnn: boolean;
326
+ /** OPFS: `navigator.storage.getDirectory` exists AND resolved. */
327
+ opfs: boolean;
328
+ /** Result of `navigator.storage.persisted()` where supported. */
329
+ persistedStorage?: boolean;
330
+ indexedDB: boolean;
331
+ cacheApi: boolean;
332
+ serviceWorker: boolean;
333
+ webWorkers: boolean;
334
+ offscreenCanvas: boolean;
335
+ webLocks: boolean;
336
+ broadcastChannel: boolean;
337
+ wakeLock: boolean;
338
+ computePressure: boolean;
339
+ performanceMemory: boolean;
340
+ measureUserAgentSpecificMemory: boolean;
341
+ schedulerYield: boolean;
342
+ webCodecs: boolean;
343
+ audioWorklet: boolean;
344
+ mediaDevices: boolean;
345
+ webTransport: boolean;
346
+ /** Chrome Built-in AI (Gemini Nano) surfaces, by `availability()` verdict when reachable. */
347
+ promptApi?: string;
348
+ summarizerApi?: string;
349
+ translatorApi?: string;
350
+ languageDetectorApi?: string;
351
+ }
352
+ /** Network Information API (Chromium + Android) snapshot at capture time. */
353
+ interface NetworkInfo {
354
+ supported: boolean;
355
+ effectiveType?: string;
356
+ /** Connection type (wifi / cellular / ethernet / ...) where the UA exposes it. */
357
+ type?: string;
358
+ downlinkMbps?: number;
359
+ rttMs?: number;
360
+ saveData?: boolean;
361
+ online?: boolean;
362
+ }
363
+ /** Display / viewport snapshot. */
364
+ interface DisplayInfo {
365
+ width: number;
366
+ height: number;
367
+ availWidth?: number;
368
+ availHeight?: number;
369
+ dpr: number;
370
+ colorDepth?: number;
371
+ orientation?: string;
372
+ viewportWidth?: number;
373
+ viewportHeight?: number;
374
+ /** `(dynamic-range: high)` media query. */
375
+ hdr?: boolean;
376
+ /** `(color-gamut: p3)` media query. */
377
+ wideGamut?: boolean;
378
+ /** `screen.isExtended` (Window Management API) — more than one display attached. */
379
+ isExtended?: boolean;
380
+ /** Reduced-motion / forced-colors preferences, cheap OS-level signals. */
381
+ prefersReducedMotion?: boolean;
382
+ prefersColorScheme?: 'light' | 'dark' | 'no-preference';
383
+ }
384
+ /** Locale / clock signals. */
385
+ interface LocaleInfo {
386
+ timeZone?: string;
387
+ /** Minutes offset from UTC at capture time (`Date#getTimezoneOffset`). */
388
+ timeZoneOffsetMinutes?: number;
389
+ locale?: string;
390
+ /** `Intl.DateTimeFormat().resolvedOptions().calendar`. */
391
+ calendar?: string;
221
392
  }
222
- /** Full environment capture for a run. Clamped fields are labeled as such. */
393
+ /**
394
+ * Full environment capture for a run. Every field beyond the first block is
395
+ * additive and best-effort: a probe that fails records nothing for its key and
396
+ * never affects the others. Clamped or capped fields are labeled as such.
397
+ */
223
398
  interface EnvironmentCapture {
224
399
  capturedAt: string;
225
400
  browser: BrowserInfo;
@@ -231,23 +406,46 @@ interface EnvironmentCapture {
231
406
  /** navigator.deviceMemory (GB) — Chromium-only, capped at 8. */
232
407
  deviceMemoryGB: number | null;
233
408
  deviceMemoryCapped: boolean;
409
+ /** `performance.memory.jsHeapSizeLimit` (Chromium) — the V8 heap ceiling for this tab. */
410
+ jsHeapSizeLimitBytes?: number;
411
+ /** `performance.memory.usedJSHeapSize` at capture (the idle baseline). */
412
+ jsHeapUsedBytes?: number;
234
413
  };
235
414
  gpu: GPUInfo;
236
415
  /** WebGL renderer string, a secondary GPU identity signal. */
237
416
  webglRenderer: string | null;
417
+ /** Detailed WebGL identity + capacity (superset of `webglRenderer`). */
418
+ webgl?: WebGLInfo;
419
+ /**
420
+ * GPU model parsed from the WebGL renderer string (ANGLE unwrapped),
421
+ * e.g. "Apple M4", "NVIDIA GeForce RTX 4070", "Mali-G78 MP20". Absent when
422
+ * no WebGL context could be created.
423
+ */
424
+ gpuModel?: string;
238
425
  flags: {
239
426
  crossOriginIsolated: boolean;
240
427
  sharedArrayBuffer: boolean;
241
428
  wasmSimd: boolean;
429
+ /** `window.isSecureContext`. */
430
+ secureContext?: boolean;
431
+ /** Full WebAssembly proposal matrix (superset of `wasmSimd`). */
432
+ wasm?: WasmFeatureSupport;
242
433
  };
434
+ /** Presence checks for the APIs the runtimes depend on. */
435
+ apis?: APIAvailability;
436
+ device?: DeviceInfo;
243
437
  storage: {
244
438
  quotaBytes?: number;
245
439
  usageBytes?: number;
440
+ usageDetails?: Record<string, number>;
246
441
  } | null;
247
442
  power: {
248
443
  batterySupported: boolean;
249
444
  charging?: boolean;
250
445
  level?: number;
446
+ /** Seconds until full / empty (Infinity serialized as absent). */
447
+ chargingTimeSec?: number;
448
+ dischargingTimeSec?: number;
251
449
  };
252
450
  pressure: {
253
451
  supported: boolean;
@@ -260,7 +458,17 @@ interface EnvironmentCapture {
260
458
  height: number;
261
459
  dpr: number;
262
460
  } | null;
461
+ /** Detailed display snapshot (superset of `screen`). */
462
+ display?: DisplayInfo;
463
+ network?: NetworkInfo;
464
+ locale?: LocaleInfo;
263
465
  languages?: string[];
466
+ /** Raw `navigator.userAgent` — kept verbatim so future parsers can re-derive fields. */
467
+ userAgent?: string;
468
+ /** Page origin the run executed on (distinguishes production from local/staging). */
469
+ pageOrigin?: string;
470
+ /** `document.visibilityState` at capture; a hidden tab is throttled. */
471
+ visibilityState?: string;
264
472
  /** Free-text device self-report — displayed as "user-reported", never trusted. */
265
473
  userReportedDevice?: string;
266
474
  }
@@ -319,17 +527,28 @@ interface CellSummary {
319
527
  qualityParseRate?: number;
320
528
  highVariance: boolean;
321
529
  }
530
+ /** Identity of the software that produced a run. */
531
+ interface HarnessInfo {
532
+ name: string;
533
+ version: string;
534
+ appVersion?: string;
535
+ /**
536
+ * Versions of the runtime packages bundled into the harness at build time
537
+ * (e.g. `{ "@huggingface/transformers": "4.2.0", "@wllama/wllama": "3.5.1" }`),
538
+ * keyed by npm package name. Per-cell `runtimeVersion` names the same value
539
+ * for the runtime that produced that cell.
540
+ */
541
+ runtimeVersions?: Record<string, string>;
542
+ /** Git commit of the harness build where the host exposes it. */
543
+ commit?: string;
544
+ }
322
545
  /** The unit of submission: one full suite run on one device. */
323
546
  interface BenchRunResult {
324
547
  protocol: typeof BENCH_PROTOCOL_VERSION;
325
548
  schemaVersion: typeof BENCH_SCHEMA_VERSION;
326
549
  runId: string;
327
550
  createdAt: string;
328
- harness: {
329
- name: string;
330
- version: string;
331
- appVersion?: string;
332
- };
551
+ harness: HarnessInfo;
333
552
  suite: BenchSuiteId;
334
553
  environment: EnvironmentCapture;
335
554
  fingerprint: FingerprintResult | null;
@@ -564,11 +783,7 @@ interface RunSuiteOptions {
564
783
  policy: RunPolicy;
565
784
  llmAdapters: ReadonlyMap<string, LLMRuntimeAdapter>;
566
785
  embedAdapters: ReadonlyMap<string, EmbeddingRuntimeAdapter>;
567
- harness: {
568
- name: string;
569
- version: string;
570
- appVersion?: string;
571
- };
786
+ harness: HarnessInfo;
572
787
  hooks?: RunnerHooks;
573
788
  abortSignal?: AbortSignal;
574
789
  /** Skip the fingerprint microbenchmark (tests only; submissions require it). */
@@ -595,6 +810,11 @@ declare function runBenchmarkSuite(options: RunSuiteOptions): Promise<BenchRunRe
595
810
  * provenance: UA Client Hints on Chromium; UA parsing elsewhere with the OS
596
811
  * version marked 'unknown-frozen' (UA strings are frozen by design on Gecko
597
812
  * and WebKit). Clamped fields (cores, deviceMemory) are labeled clamped.
813
+ *
814
+ * Everything a browser will disclose is recorded, whether or not the current
815
+ * analysis uses it: WebGPU + WebGL identity, the WebAssembly proposal matrix,
816
+ * API availability, form factor, display, network, locale, power. Every probe
817
+ * is individually guarded; a failing probe records nothing for its key.
598
818
  */
599
819
 
600
820
  /**
@@ -609,6 +829,64 @@ declare function runBenchmarkSuite(options: RunSuiteOptions): Promise<BenchRunRe
609
829
  declare function captureEnvironment(options?: {
610
830
  userReportedDevice?: string;
611
831
  }): Promise<EnvironmentCapture>;
832
+ /**
833
+ * UA-string fallback for browsers without UA Client Hints (every WebKit
834
+ * browser). Conservative: browser name + version token, platform, and the OS
835
+ * version only where the UA genuinely carries one.
836
+ *
837
+ * @example
838
+ * parseUserAgent('... CriOS/145.0.7632.72 Mobile/15E148 Safari/604.1').browser.name; // 'Chrome iOS'
839
+ */
840
+ declare function parseUserAgent(ua: string): {
841
+ browser: BrowserInfo;
842
+ os: OSInfo;
843
+ };
844
+ /**
845
+ * Rendering engine from the UA. Every iOS browser is WebKit regardless of its
846
+ * brand (App Store policy), so the iOS check comes first.
847
+ *
848
+ * @example
849
+ * detectEngine('... CriOS/145.0 ...'); // 'WebKit'
850
+ */
851
+ declare function detectEngine(ua: string): BrowserInfo['engine'];
852
+ /** Inputs to the form-factor derivation, each optional. */
853
+ interface DeviceTypeSignals {
854
+ ua: string;
855
+ maxTouchPoints: number;
856
+ /** UA-CH `formFactors` high-entropy hint (Chromium 125+). */
857
+ formFactors?: string[];
858
+ /** UA-CH `mobile` bit. */
859
+ mobile?: boolean;
860
+ }
861
+ /**
862
+ * Derive a form factor. UA-CH form factors win when present; otherwise the UA
863
+ * decides, with `maxTouchPoints` unmasking an iPad that reports itself as a
864
+ * Mac (iPadOS 13+ default) and separating Android tablets (no `Mobile` token)
865
+ * from phones.
866
+ *
867
+ * @example
868
+ * deriveDeviceType({ ua: navigator.userAgent, maxTouchPoints: navigator.maxTouchPoints });
869
+ */
870
+ declare function deriveDeviceType(signals: DeviceTypeSignals): DeviceType;
871
+ /**
872
+ * GPU model from a WebGL renderer string. ANGLE wraps the model as
873
+ * `ANGLE (<vendor>, <model>[ (0x...)] <backend...>, <api>)`; Metal adds a
874
+ * `ANGLE Metal Renderer: ` prefix. Native strings are returned as-is.
875
+ *
876
+ * @example
877
+ * parseGpuModel('ANGLE (Apple, ANGLE Metal Renderer: Apple M4, Unspecified Version)'); // 'Apple M4'
878
+ */
879
+ declare function parseGpuModel(renderer: string | null | undefined): string | undefined;
880
+ /**
881
+ * WebAssembly proposal support, probed the way `wasm-feature-detect` does:
882
+ * validate or compile the smallest module that uses each feature. The byte
883
+ * sequences are those of wasm-feature-detect 1.9.0, inlined so the harness
884
+ * keeps its zero-dependency contract.
885
+ *
886
+ * @example
887
+ * const wasm = await detectWasmFeatures(); // { simd: true, threads: true, ... }
888
+ */
889
+ declare function detectWasmFeatures(): Promise<WasmFeatureSupport>;
612
890
 
613
891
  /**
614
892
  * Memory sampling at protocol points (baseline / post-load / post-run).
@@ -997,4 +1275,4 @@ interface STSPair {
997
1275
  /** 100-pair STS-B test subset (order preserved from the source dataset). */
998
1276
  declare const STSB_SUBSET: readonly STSPair[];
999
1277
 
1000
- export { type AdapterAvailability, type AdapterLoadProgress, BENCH_PROTOCOL_VERSION, BENCH_SCHEMA_VERSION, type BenchCellResult, type BenchCellStatus, type BenchChunk, type BenchEmbeddingModel, type BenchLanguageModel, type BenchModelRef, type BenchRunResult, type BenchRuntimeId, type BenchStreamChunk, type BenchSuiteId, type BenchWorkloadKind, type BenchWorkloadSpec, type BrowserInfo, type CellSummary, EMBED_WORKLOADS, type EmbedIteration, type EmbedWorkloadSpec, type EmbeddingRuntimeAdapter, type EnvironmentCapture, type FingerprintResult, GENERATION_BUDGET, type GPUInfo, HEADLINE_MIN_SUBMISSIONS, type LLMIteration, type LLMRuntimeAdapter, type LLMWorkloadSpec, LLM_WORKLOADS, type LeaderboardRow, type LoadRecord, type LoadedEmbedder, type LoadedLLM, MIN_GENERATED_CHARS, type MMLUItem, MMLU_MAX_TOKENS, MMLU_OUTPUT_CAP, type MemorySample, type MetricSummary, type OSInfo, PLAUSIBILITY_RULES_VERSION, type PlannedCell, type PlausibilityFlag, type ProviderUsage, QUALITY_WORKLOADS, type QualityResult, type QualityWorkloadSpec, RUNTIME_EXECUTION_ORDER, RUN_POLICIES, type RunPolicy, type RunSuiteOptions, type RunnerHooks, STREAM_COHERENCE_MIN_SPAN_RATIO, STSB_SUBSET, type STSPair, TINY_MMLU, type TraceEvent, TraceRecorder, USAGE_FIDELITY, type ValidationReport, WORKLOADS_BY_ID, aggregateRuns, canonicalJson, captureEnvironment, checkPlausibility, computeRunDigest, deviceClassOf, formatMMLUPrompt, geomean, hrNow, inferTimerResolutionUs, isIncrementalStream, mean, median, memoryApiAvailable, orderCells, parseMMLUAnswer, quantile, rowsToCSV, runBenchmarkSuite, runFingerprint, runMMLUFidelity, runSTSQuality, runsToLongCSV, sampleMemoryBytes, sha256Hex, sleep, spearman, stddev, summarize, summarizeCell, summarizeRun, validateRunShape, validateSubmission, verifyRunDigest };
1278
+ export { type APIAvailability, type AdapterAvailability, type AdapterLoadProgress, BENCH_PROTOCOL_VERSION, BENCH_SCHEMA_VERSION, type BenchCellResult, type BenchCellStatus, type BenchChunk, type BenchEmbeddingModel, type BenchLanguageModel, type BenchModelRef, type BenchRunResult, type BenchRuntimeId, type BenchStreamChunk, type BenchSuiteId, type BenchWorkloadKind, type BenchWorkloadSpec, type BrowserInfo, type CellSummary, type DeviceInfo, type DeviceType, type DeviceTypeSignals, type DisplayInfo, EMBED_WORKLOADS, type EmbedIteration, type EmbedWorkloadSpec, type EmbeddingRuntimeAdapter, type EnvironmentCapture, type FingerprintResult, GENERATION_BUDGET, type GPUInfo, HEADLINE_MIN_SUBMISSIONS, type HarnessInfo, type LLMIteration, type LLMRuntimeAdapter, type LLMWorkloadSpec, LLM_WORKLOADS, type LeaderboardRow, type LoadRecord, type LoadedEmbedder, type LoadedLLM, type LocaleInfo, MIN_GENERATED_CHARS, type MMLUItem, MMLU_MAX_TOKENS, MMLU_OUTPUT_CAP, type MemorySample, type MetricSummary, type NetworkInfo, type OSInfo, PLAUSIBILITY_RULES_VERSION, type PlannedCell, type PlausibilityFlag, type ProviderUsage, QUALITY_WORKLOADS, type QualityResult, type QualityWorkloadSpec, RUNTIME_EXECUTION_ORDER, RUN_POLICIES, type RunPolicy, type RunSuiteOptions, type RunnerHooks, STREAM_COHERENCE_MIN_SPAN_RATIO, STSB_SUBSET, type STSPair, TINY_MMLU, type TraceEvent, TraceRecorder, USAGE_FIDELITY, type ValidationReport, WORKLOADS_BY_ID, type WasmFeatureSupport, type WebGLInfo, aggregateRuns, canonicalJson, captureEnvironment, checkPlausibility, computeRunDigest, deriveDeviceType, detectEngine, detectWasmFeatures, deviceClassOf, formatMMLUPrompt, geomean, hrNow, inferTimerResolutionUs, isIncrementalStream, mean, median, memoryApiAvailable, orderCells, parseGpuModel, parseMMLUAnswer, parseUserAgent, quantile, rowsToCSV, runBenchmarkSuite, runFingerprint, runMMLUFidelity, runSTSQuality, runsToLongCSV, sampleMemoryBytes, sha256Hex, sleep, spearman, stddev, summarize, summarizeCell, summarizeRun, validateRunShape, validateSubmission, verifyRunDigest };