@trillboards/edge-sdk 0.2.92 → 0.2.94
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/deploy/detector/bench/litert-twin-parity.json +313 -0
- package/deploy/detector/bench/twin_parity_contract.py +113 -0
- package/deploy/detector/bench/verify_litert_twin_parity.py +188 -0
- package/deploy/detector/tests/test_litert_twin_parity_contract.py +165 -0
- package/deploy/detector/tests/test_onnx_artifact_probe.py +618 -0
- package/deploy/detector/trillboards_detector/labels.py +181 -1
- package/dist/EdgeAgent.js +1 -1
- package/dist/diagnose.d.ts +1 -1
- package/dist/diagnose.js +1 -1
- package/package.json +9 -2
|
@@ -347,7 +347,183 @@ RFDETR_MEDIUM = ModelVocabulary(
|
|
|
347
347
|
#: nothing (see `ClassIndex`, built over models whose file is present), and
|
|
348
348
|
#: publishing is a separate task. What changed is that the service can now
|
|
349
349
|
#: EXPRESS a second entry, which before this it structurally could not.
|
|
350
|
-
|
|
350
|
+
#: Forklift Detector — published 2026-08-25 by
|
|
351
|
+
#: scripts/sensing/publish-sensing-model.js. The class list is the artifact's own
|
|
352
|
+
#: (graph metadata key 'names'); the footprint is MEASURED, 119.0938 MiB after a
|
|
353
|
+
#: probe inference via rusage-maxrss, not an estimate from the file size.
|
|
354
|
+
#: Coordinate space MEASURED, not assumed: max|box channel| = 640.0000 over 110 real frames; / imgsz 640 = 1.0000. pixels at >= 0.2, normalized at <= 0.02, refused in between.
|
|
355
|
+
GH_FORKLIFT_COMBINE_CLASS_NAMES: "MappingProxyType[int, str]" = MappingProxyType({
|
|
356
|
+
0: "forklift",
|
|
357
|
+
1: "forklift partial",
|
|
358
|
+
})
|
|
359
|
+
|
|
360
|
+
GH_FORKLIFT_COMBINE = ModelVocabulary(
|
|
361
|
+
model_name="gh_forklift_combine",
|
|
362
|
+
slot_names=GH_FORKLIFT_COMBINE_CLASS_NAMES,
|
|
363
|
+
logit_slots=2,
|
|
364
|
+
approx_ram_bytes=124878901,
|
|
365
|
+
onnx_variant=VariantContract(
|
|
366
|
+
output_layout="anchor_4_plus_nc",
|
|
367
|
+
box_units="pixels",
|
|
368
|
+
box_scale_to_pixels=1.0,
|
|
369
|
+
),
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
#: PPE Detector (hard hat) — published 2026-08-25 by
|
|
373
|
+
#: scripts/sensing/publish-sensing-model.js. The class list is the artifact's own
|
|
374
|
+
#: (graph metadata key 'names'); the footprint is MEASURED, 420.5156 MiB after a
|
|
375
|
+
#: probe inference via rusage-maxrss, not an estimate from the file size.
|
|
376
|
+
#: Coordinate space MEASURED, not assumed: max|box channel| = 640.0000 over 110 real frames; / imgsz 640 = 1.0000. pixels at >= 0.2, normalized at <= 0.02, refused in between.
|
|
377
|
+
PPE_VYRA_14CLS_V8M_CLASS_NAMES: "MappingProxyType[int, str]" = MappingProxyType({
|
|
378
|
+
0: "fall detected",
|
|
379
|
+
1: "gloves",
|
|
380
|
+
2: "goggles",
|
|
381
|
+
3: "hardhat",
|
|
382
|
+
4: "ladder",
|
|
383
|
+
5: "mask",
|
|
384
|
+
6: "no gloves",
|
|
385
|
+
7: "no goggles",
|
|
386
|
+
8: "no hardhat",
|
|
387
|
+
9: "no mask",
|
|
388
|
+
10: "no safety vest",
|
|
389
|
+
11: "person",
|
|
390
|
+
12: "safety cone",
|
|
391
|
+
13: "safety vest",
|
|
392
|
+
})
|
|
393
|
+
|
|
394
|
+
PPE_VYRA_14CLS_V8M = ModelVocabulary(
|
|
395
|
+
model_name="ppe_vyra_14cls_v8m",
|
|
396
|
+
slot_names=PPE_VYRA_14CLS_V8M_CLASS_NAMES,
|
|
397
|
+
logit_slots=14,
|
|
398
|
+
approx_ram_bytes=440942566,
|
|
399
|
+
onnx_variant=VariantContract(
|
|
400
|
+
output_layout="anchor_4_plus_nc",
|
|
401
|
+
box_units="pixels",
|
|
402
|
+
box_scale_to_pixels=1.0,
|
|
403
|
+
),
|
|
404
|
+
)
|
|
405
|
+
|
|
406
|
+
#: Heavy Machinery Detector — published 2026-08-25 by
|
|
407
|
+
#: scripts/sensing/publish-sensing-model.js. The class list is the artifact's own
|
|
408
|
+
#: (graph metadata key 'names'); the footprint is MEASURED, 118.6875 MiB after a
|
|
409
|
+
#: probe inference via rusage-maxrss, not an estimate from the file size.
|
|
410
|
+
#: Coordinate space MEASURED, not assumed: max|box channel| = 1832.0278 over 120 real frames; / imgsz 640 = 2.8625. pixels at >= 0.2, normalized at <= 0.02, refused in between.
|
|
411
|
+
PPE_CONSTRUCTION_17CLS_V8N_CLASS_NAMES: "MappingProxyType[int, str]" = MappingProxyType({
|
|
412
|
+
0: "barricade",
|
|
413
|
+
1: "dumpster",
|
|
414
|
+
2: "excavators",
|
|
415
|
+
3: "gloves",
|
|
416
|
+
4: "hardhat",
|
|
417
|
+
5: "mask",
|
|
418
|
+
6: "no hardhat",
|
|
419
|
+
7: "no mask",
|
|
420
|
+
8: "no safety vest",
|
|
421
|
+
9: "person",
|
|
422
|
+
10: "safety net",
|
|
423
|
+
11: "safety shoes",
|
|
424
|
+
12: "safety vest",
|
|
425
|
+
13: "dump truck",
|
|
426
|
+
14: "mini van",
|
|
427
|
+
15: "truck",
|
|
428
|
+
16: "wheel loader",
|
|
429
|
+
})
|
|
430
|
+
|
|
431
|
+
PPE_CONSTRUCTION_17CLS_V8N = ModelVocabulary(
|
|
432
|
+
model_name="ppe_construction_17cls_v8n",
|
|
433
|
+
slot_names=PPE_CONSTRUCTION_17CLS_V8N_CLASS_NAMES,
|
|
434
|
+
logit_slots=17,
|
|
435
|
+
approx_ram_bytes=124452864,
|
|
436
|
+
onnx_variant=VariantContract(
|
|
437
|
+
output_layout="anchor_4_plus_nc",
|
|
438
|
+
box_units="pixels",
|
|
439
|
+
box_scale_to_pixels=1.0,
|
|
440
|
+
),
|
|
441
|
+
)
|
|
442
|
+
|
|
443
|
+
#: Fire-Safety Detector — published 2026-08-25 by
|
|
444
|
+
#: scripts/sensing/publish-sensing-model.js. The class list is the artifact's own
|
|
445
|
+
#: (graph metadata key 'names'); the footprint is MEASURED, 239.25 MiB after a
|
|
446
|
+
#: probe inference via rusage-maxrss, not an estimate from the file size.
|
|
447
|
+
#: Coordinate space MEASURED, not assumed: max|box channel| = 1971.5000 over 100 real frames; / imgsz 640 = 3.0805. pixels at >= 0.2, normalized at <= 0.02, refused in between.
|
|
448
|
+
PPE_KILLUMINATI_19CLS_V8S_CLASS_NAMES: "MappingProxyType[int, str]" = MappingProxyType({
|
|
449
|
+
0: "boots",
|
|
450
|
+
1: "ear protection",
|
|
451
|
+
2: "glass",
|
|
452
|
+
3: "glove",
|
|
453
|
+
4: "hard hat",
|
|
454
|
+
5: "mask",
|
|
455
|
+
6: "no boots",
|
|
456
|
+
7: "no ear protection",
|
|
457
|
+
8: "no glass",
|
|
458
|
+
9: "no glove",
|
|
459
|
+
10: "no helmet",
|
|
460
|
+
11: "no mask",
|
|
461
|
+
12: "no vest",
|
|
462
|
+
13: "worker",
|
|
463
|
+
14: "vest",
|
|
464
|
+
15: "circular saw",
|
|
465
|
+
16: "fire extinguisher",
|
|
466
|
+
17: "fire prevention net",
|
|
467
|
+
18: "welding equipment",
|
|
468
|
+
})
|
|
469
|
+
|
|
470
|
+
PPE_KILLUMINATI_19CLS_V8S = ModelVocabulary(
|
|
471
|
+
model_name="ppe_killuminati_19cls_v8s",
|
|
472
|
+
slot_names=PPE_KILLUMINATI_19CLS_V8S_CLASS_NAMES,
|
|
473
|
+
logit_slots=19,
|
|
474
|
+
approx_ram_bytes=250871808,
|
|
475
|
+
onnx_variant=VariantContract(
|
|
476
|
+
output_layout="anchor_4_plus_nc",
|
|
477
|
+
box_units="pixels",
|
|
478
|
+
box_scale_to_pixels=1.0,
|
|
479
|
+
),
|
|
480
|
+
)
|
|
481
|
+
|
|
482
|
+
#: FIVE SPECIALISTS WERE SCORED; FOUR ARE HERE. `gh_fall_tonlong` IS ABSENT ON
|
|
483
|
+
#: PURPOSE, AND THIS NOTE IS WHY IT MUST STAY ABSENT.
|
|
484
|
+
#:
|
|
485
|
+
#: It has a committed score card and a committed 94-frame eval set, and its
|
|
486
|
+
#: numbers are good — the `fall` gate fits at 0.7924 with precision 1.0 and
|
|
487
|
+
#: recall 1.0 on the held-out half. It is not withheld for being weak.
|
|
488
|
+
#:
|
|
489
|
+
#: It is withheld because its own exporter named two logit slots the same word:
|
|
490
|
+
#: the graph's `names` metadata is
|
|
491
|
+
#:
|
|
492
|
+
#: {0: 'Violence', 1: 'fall', 2: 'fire', 3: 'sit', 4: 'sleep',
|
|
493
|
+
#: 5: 'standing', 6: 'violence'}
|
|
494
|
+
#:
|
|
495
|
+
#: and `normalize_class_name` lowercases, so slots 0 and 6 both fold to
|
|
496
|
+
#: `violence`. SEVEN logit slots, SIX names. `ModelVocabulary.__post_init__`
|
|
497
|
+
#: refuses that pair — "two slots share one class name, so a filter would be
|
|
498
|
+
#: ambiguous" — because `_to_wire` puts the declared name on the wire and
|
|
499
|
+
#: `postprocess` filters on the canonical one, so the service could not attribute
|
|
500
|
+
#: a `violence` detection to a slot. The refusal is at CONSTRUCTION, so the
|
|
501
|
+
#: artifact would not load on a device: a registry row for it would be a row for
|
|
502
|
+
#: a model that can never answer, which is the `yolov8_nano` shape this whole
|
|
503
|
+
#: publish path exists to stop.
|
|
504
|
+
#:
|
|
505
|
+
#: AND IT CANNOT BE PAPERED OVER FROM OUR SIDE. `_resolve_slot_names` in
|
|
506
|
+
#: `scripts/sensing/onnx_artifact_probe.py` is deliberately NOT a precedence
|
|
507
|
+
#: order — every source that exists must AGREE — so a `--classes-file` cannot
|
|
508
|
+
#: override the graph, only restate it, collision included. Renaming one of the
|
|
509
|
+
#: two would also be a guess about which logit the exporter wired, and a wrong
|
|
510
|
+
#: guess is invisible: the boxes stay real and the counts stay plausible while
|
|
511
|
+
#: every `violence` answer names the wrong slot.
|
|
512
|
+
#:
|
|
513
|
+
#: WHAT UNBLOCKS IT is a re-export with one spelling per class, which changes the
|
|
514
|
+
#: bytes and therefore the sha256 — so it is a NEW artifact that must be scored
|
|
515
|
+
#: again before it can ship. `person_fall` is already a legal `corpus_name` in
|
|
516
|
+
#: both CHECK constraints and holds zero fixtures, which is inert while no
|
|
517
|
+
#: registry row names it (and `publish-sensing-model.js` refuses to deploy
|
|
518
|
+
#: against an empty corpus), so the family is ready for that artifact and is
|
|
519
|
+
#: waiting on nothing else.
|
|
520
|
+
#:
|
|
521
|
+
#: The collision is not folklore: `tests/test_onnx_artifact_probe.py`
|
|
522
|
+
#: (TestFourPlusNcCountsLogitSlots) pins `slot_map[0] == slot_map[6]` and uses
|
|
523
|
+
#: this artifact as the fixture that exercises `_verify_class_axis_width`, where
|
|
524
|
+
#: `4 + 7 = 11` matches its real `[1, 11, 8400]` head and `4 + 6 = 10` would
|
|
525
|
+
#: reject it.
|
|
526
|
+
BUILTIN_VOCABULARIES: "tuple[ModelVocabulary, ...]" = (RFDETR_MEDIUM, GH_FORKLIFT_COMBINE, PPE_VYRA_14CLS_V8M, PPE_CONSTRUCTION_17CLS_V8N, PPE_KILLUMINATI_19CLS_V8S,)
|
|
351
527
|
|
|
352
528
|
|
|
353
529
|
class ClassIndex:
|
|
@@ -441,6 +617,10 @@ class ClassIndex:
|
|
|
441
617
|
|
|
442
618
|
|
|
443
619
|
__all__ = [
|
|
620
|
+
"PPE_KILLUMINATI_19CLS_V8S",
|
|
621
|
+
"PPE_CONSTRUCTION_17CLS_V8N",
|
|
622
|
+
"PPE_VYRA_14CLS_V8M",
|
|
623
|
+
"GH_FORKLIFT_COMBINE",
|
|
444
624
|
"ANCHOR_4_PLUS_NC",
|
|
445
625
|
"BOX_UNITS",
|
|
446
626
|
"BOX_UNITS_NORMALIZED",
|
package/dist/EdgeAgent.js
CHANGED
|
@@ -44,7 +44,7 @@ const edge_ads_1 = require("@trillboards/edge-ads");
|
|
|
44
44
|
const CommandRouter_1 = require("./CommandRouter");
|
|
45
45
|
const config_1 = require("./config");
|
|
46
46
|
const dataDir_1 = require("./dataDir");
|
|
47
|
-
const SDK_VERSION = '0.2.
|
|
47
|
+
const SDK_VERSION = '0.2.94';
|
|
48
48
|
class EdgeAgent extends events_1.EventEmitter {
|
|
49
49
|
constructor(config, deps) {
|
|
50
50
|
super();
|
package/dist/diagnose.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ export interface DiagnosticReport {
|
|
|
31
31
|
skipped: number;
|
|
32
32
|
};
|
|
33
33
|
}
|
|
34
|
-
declare const SDK_VERSION = "0.2.
|
|
34
|
+
declare const SDK_VERSION = "0.2.94";
|
|
35
35
|
declare function checkNodeVersion(): CheckResult;
|
|
36
36
|
declare function checkPlatform(): CheckResult;
|
|
37
37
|
declare function checkMemory(): CheckResult;
|
package/dist/diagnose.js
CHANGED
|
@@ -63,7 +63,7 @@ const localNetworkAccess_1 = require("./localNetworkAccess");
|
|
|
63
63
|
// ---------------------------------------------------------------------------
|
|
64
64
|
// SDK version — mirrors package.json; kept in sync by CI
|
|
65
65
|
// ---------------------------------------------------------------------------
|
|
66
|
-
const SDK_VERSION = '0.2.
|
|
66
|
+
const SDK_VERSION = '0.2.94';
|
|
67
67
|
exports._SDK_VERSION = SDK_VERSION;
|
|
68
68
|
// ---------------------------------------------------------------------------
|
|
69
69
|
// ANSI helpers (no external deps)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trillboards/edge-sdk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.94",
|
|
4
4
|
"description": "Composable cross-platform Edge AI SDK for audience sensing on DOOH/CTV devices",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -30,7 +30,14 @@
|
|
|
30
30
|
"@trillboards/edge-platform-rtsp": "^0.2.0",
|
|
31
31
|
"@trillboards/edge-platform-windows": "^0.2.0"
|
|
32
32
|
},
|
|
33
|
-
"files": [
|
|
33
|
+
"files": [
|
|
34
|
+
"dist",
|
|
35
|
+
"configs",
|
|
36
|
+
"deploy",
|
|
37
|
+
"LICENSE",
|
|
38
|
+
"THIRD-PARTY-NOTICES.md",
|
|
39
|
+
"README.md"
|
|
40
|
+
],
|
|
34
41
|
"engines": {
|
|
35
42
|
"node": ">=18.0.0"
|
|
36
43
|
},
|