@camstack/types 1.2.308 → 1.2.309

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.
Files changed (33) hide show
  1. package/dist/capabilities/custom-model-registry.cap.d.ts +38 -4
  2. package/dist/capabilities/device-manager.cap.d.ts +8 -8
  3. package/dist/capabilities/hub-address.d.ts +76 -0
  4. package/dist/capabilities/index.d.ts +4 -3
  5. package/dist/capabilities/local-network.cap.d.ts +93 -0
  6. package/dist/capabilities/model-convert.cap.d.ts +19 -2
  7. package/dist/capabilities/model-distributor.cap.d.ts +38 -4
  8. package/dist/capabilities/pipeline-executor.cap.d.ts +124 -10
  9. package/dist/capabilities/pipeline-runner.cap.d.ts +13 -0
  10. package/dist/catalogs/frigate-plus-classmap.d.ts +10 -7
  11. package/dist/catalogs/index.d.ts +1 -1
  12. package/dist/catalogs/root-model-supply.d.ts +202 -0
  13. package/dist/client.js +51 -49
  14. package/dist/client.mjs +51 -49
  15. package/dist/device/location-icon.d.ts +4 -4
  16. package/dist/device/site-zone.d.ts +2 -2
  17. package/dist/ffmpeg/pinned-spawn.d.ts +1 -1
  18. package/dist/generated/addon-api.d.ts +14 -0
  19. package/dist/generated/method-access-map.d.ts +1 -1
  20. package/dist/generated/system-proxy.d.ts +1 -1
  21. package/dist/index.d.ts +2 -1
  22. package/dist/index.js +961 -512
  23. package/dist/index.mjs +931 -500
  24. package/dist/interfaces/event-bus.d.ts +12 -6
  25. package/dist/interfaces/pipeline-executor-capability.d.ts +6 -1
  26. package/dist/node.js +1 -1
  27. package/dist/node.mjs +1 -1
  28. package/dist/pipeline/root-face-crop.d.ts +31 -0
  29. package/dist/types/detection.d.ts +9 -0
  30. package/dist/types/models.d.ts +69 -8
  31. package/dist/types/pipeline-step.d.ts +6 -0
  32. package/package.json +1 -1
  33. package/dist/catalogs/classifier-fill.d.ts +0 -104
package/dist/index.js CHANGED
@@ -5346,424 +5346,40 @@ function resolveClipSearchMinScore(meta, request) {
5346
5346
  return Math.min(1, Math.round(meta.searchMinScore * factor * 1e3) / 1e3);
5347
5347
  }
5348
5348
  //#endregion
5349
- //#region src/catalogs/coco-classmap.ts
5350
- var COCO_80_LABELS = [
5351
- {
5352
- id: "person",
5353
- name: "Person"
5354
- },
5355
- {
5356
- id: "bicycle",
5357
- name: "Bicycle"
5358
- },
5359
- {
5360
- id: "car",
5361
- name: "Car"
5362
- },
5363
- {
5364
- id: "motorcycle",
5365
- name: "Motorcycle"
5366
- },
5367
- {
5368
- id: "airplane",
5369
- name: "Airplane"
5370
- },
5371
- {
5372
- id: "bus",
5373
- name: "Bus"
5374
- },
5375
- {
5376
- id: "train",
5377
- name: "Train"
5378
- },
5379
- {
5380
- id: "truck",
5381
- name: "Truck"
5382
- },
5383
- {
5384
- id: "boat",
5385
- name: "Boat"
5386
- },
5387
- {
5388
- id: "traffic light",
5389
- name: "Traffic Light"
5390
- },
5391
- {
5392
- id: "fire hydrant",
5393
- name: "Fire Hydrant"
5394
- },
5395
- {
5396
- id: "stop sign",
5397
- name: "Stop Sign"
5398
- },
5399
- {
5400
- id: "parking meter",
5401
- name: "Parking Meter"
5402
- },
5403
- {
5404
- id: "bench",
5405
- name: "Bench"
5406
- },
5407
- {
5408
- id: "bird",
5409
- name: "Bird"
5410
- },
5411
- {
5412
- id: "cat",
5413
- name: "Cat"
5414
- },
5415
- {
5416
- id: "dog",
5417
- name: "Dog"
5418
- },
5419
- {
5420
- id: "horse",
5421
- name: "Horse"
5422
- },
5423
- {
5424
- id: "sheep",
5425
- name: "Sheep"
5426
- },
5427
- {
5428
- id: "cow",
5429
- name: "Cow"
5430
- },
5431
- {
5432
- id: "elephant",
5433
- name: "Elephant"
5434
- },
5435
- {
5436
- id: "bear",
5437
- name: "Bear"
5438
- },
5439
- {
5440
- id: "zebra",
5441
- name: "Zebra"
5442
- },
5443
- {
5444
- id: "giraffe",
5445
- name: "Giraffe"
5446
- },
5447
- {
5448
- id: "backpack",
5449
- name: "Backpack"
5450
- },
5451
- {
5452
- id: "umbrella",
5453
- name: "Umbrella"
5454
- },
5455
- {
5456
- id: "handbag",
5457
- name: "Handbag"
5458
- },
5459
- {
5460
- id: "tie",
5461
- name: "Tie"
5462
- },
5463
- {
5464
- id: "suitcase",
5465
- name: "Suitcase"
5466
- },
5467
- {
5468
- id: "frisbee",
5469
- name: "Frisbee"
5470
- },
5471
- {
5472
- id: "skis",
5473
- name: "Skis"
5474
- },
5475
- {
5476
- id: "snowboard",
5477
- name: "Snowboard"
5478
- },
5479
- {
5480
- id: "sports ball",
5481
- name: "Sports Ball"
5482
- },
5483
- {
5484
- id: "kite",
5485
- name: "Kite"
5486
- },
5487
- {
5488
- id: "baseball bat",
5489
- name: "Baseball Bat"
5490
- },
5491
- {
5492
- id: "baseball glove",
5493
- name: "Baseball Glove"
5494
- },
5495
- {
5496
- id: "skateboard",
5497
- name: "Skateboard"
5498
- },
5499
- {
5500
- id: "surfboard",
5501
- name: "Surfboard"
5502
- },
5503
- {
5504
- id: "tennis racket",
5505
- name: "Tennis Racket"
5506
- },
5507
- {
5508
- id: "bottle",
5509
- name: "Bottle"
5510
- },
5511
- {
5512
- id: "wine glass",
5513
- name: "Wine Glass"
5514
- },
5515
- {
5516
- id: "cup",
5517
- name: "Cup"
5518
- },
5519
- {
5520
- id: "fork",
5521
- name: "Fork"
5522
- },
5523
- {
5524
- id: "knife",
5525
- name: "Knife"
5526
- },
5527
- {
5528
- id: "spoon",
5529
- name: "Spoon"
5530
- },
5531
- {
5532
- id: "bowl",
5533
- name: "Bowl"
5534
- },
5535
- {
5536
- id: "banana",
5537
- name: "Banana"
5538
- },
5539
- {
5540
- id: "apple",
5541
- name: "Apple"
5542
- },
5543
- {
5544
- id: "sandwich",
5545
- name: "Sandwich"
5546
- },
5547
- {
5548
- id: "orange",
5549
- name: "Orange"
5550
- },
5551
- {
5552
- id: "broccoli",
5553
- name: "Broccoli"
5554
- },
5555
- {
5556
- id: "carrot",
5557
- name: "Carrot"
5558
- },
5559
- {
5560
- id: "hot dog",
5561
- name: "Hot Dog"
5562
- },
5563
- {
5564
- id: "pizza",
5565
- name: "Pizza"
5566
- },
5567
- {
5568
- id: "donut",
5569
- name: "Donut"
5570
- },
5571
- {
5572
- id: "cake",
5573
- name: "Cake"
5574
- },
5575
- {
5576
- id: "chair",
5577
- name: "Chair"
5578
- },
5579
- {
5580
- id: "couch",
5581
- name: "Couch"
5582
- },
5583
- {
5584
- id: "potted plant",
5585
- name: "Potted Plant"
5586
- },
5587
- {
5588
- id: "bed",
5589
- name: "Bed"
5590
- },
5591
- {
5592
- id: "dining table",
5593
- name: "Dining Table"
5594
- },
5595
- {
5596
- id: "toilet",
5597
- name: "Toilet"
5598
- },
5599
- {
5600
- id: "tv",
5601
- name: "TV"
5602
- },
5603
- {
5604
- id: "laptop",
5605
- name: "Laptop"
5606
- },
5607
- {
5608
- id: "mouse",
5609
- name: "Mouse"
5610
- },
5611
- {
5612
- id: "remote",
5613
- name: "Remote"
5614
- },
5615
- {
5616
- id: "keyboard",
5617
- name: "Keyboard"
5618
- },
5619
- {
5620
- id: "cell phone",
5621
- name: "Cell Phone"
5622
- },
5623
- {
5624
- id: "microwave",
5625
- name: "Microwave"
5626
- },
5627
- {
5628
- id: "oven",
5629
- name: "Oven"
5630
- },
5631
- {
5632
- id: "toaster",
5633
- name: "Toaster"
5634
- },
5635
- {
5636
- id: "sink",
5637
- name: "Sink"
5638
- },
5639
- {
5640
- id: "refrigerator",
5641
- name: "Refrigerator"
5642
- },
5643
- {
5644
- id: "book",
5645
- name: "Book"
5646
- },
5647
- {
5648
- id: "clock",
5649
- name: "Clock"
5650
- },
5651
- {
5652
- id: "vase",
5653
- name: "Vase"
5654
- },
5655
- {
5656
- id: "scissors",
5657
- name: "Scissors"
5658
- },
5659
- {
5660
- id: "teddy bear",
5661
- name: "Teddy Bear"
5662
- },
5663
- {
5664
- id: "hair drier",
5665
- name: "Hair Drier"
5666
- },
5667
- {
5668
- id: "toothbrush",
5669
- name: "Toothbrush"
5670
- }
5671
- ];
5672
- var MACRO_LABELS = [
5673
- {
5674
- id: "person",
5675
- name: "Person"
5676
- },
5677
- {
5678
- id: "vehicle",
5679
- name: "Vehicle"
5680
- },
5681
- {
5682
- id: "animal",
5683
- name: "Animal"
5684
- },
5685
- {
5686
- id: "package",
5687
- name: "Package"
5688
- }
5689
- ];
5690
- /**
5691
- * The class names a per-class COUNT can ever be keyed on — the macro ids, and
5692
- * only those.
5693
- *
5694
- * `preserveOriginal: false` below is the whole reason this set exists: the
5695
- * executor maps each raw COCO label onto its macro and DROPS everything else,
5696
- * so a tracked detection's `className` is always one of {@link MACRO_LABELS}.
5697
- * Any surface that indexes counts by class name — the ZoneAnalytics occupancy
5698
- * snapshot's `byClass`, and therefore every occupancy rule — can match nothing
5699
- * else. Derived from the catalog, never hand-listed, so a new macro joins it by
5700
- * being declared once.
5701
- *
5702
- * Cost of not having it, 2026-08-12: the notification rule editor offered the
5703
- * full taxonomy for an occupancy class (occupancy is the one condition that
5704
- * does not go through the engine's macro-expanding `expandClassSelector`), two
5705
- * live rules were authored on `car`, and both counters read 0 forever.
5706
- */
5707
- var DETECTION_MACRO_CLASSES = new Set(MACRO_LABELS.map((l) => l.id));
5708
- /** True when `className` is a macro the detector can actually emit (and hence a
5709
- * class a count can be keyed on) — see {@link DETECTION_MACRO_CLASSES}. */
5710
- function isDetectionMacroClass(className) {
5711
- return DETECTION_MACRO_CLASSES.has(className.trim().toLowerCase());
5712
- }
5713
- var COCO_TO_MACRO = {
5714
- mapping: {
5715
- person: "person",
5716
- bicycle: "vehicle",
5717
- car: "vehicle",
5718
- motorcycle: "vehicle",
5719
- airplane: "vehicle",
5720
- bus: "vehicle",
5721
- train: "vehicle",
5722
- truck: "vehicle",
5723
- boat: "vehicle",
5724
- bird: "animal",
5725
- cat: "animal",
5726
- dog: "animal",
5727
- horse: "animal",
5728
- sheep: "animal",
5729
- cow: "animal",
5730
- elephant: "animal",
5731
- bear: "animal",
5732
- zebra: "animal",
5733
- giraffe: "animal",
5734
- suitcase: "package",
5735
- backpack: "package",
5736
- handbag: "package"
5737
- },
5738
- preserveOriginal: false
5739
- };
5740
- //#endregion
5741
- //#region src/catalogs/classifier-fill.ts
5742
- /** Steps a root detector may declare it fills. */
5743
- var FILLABLE_STEP_IDS = [
5349
+ //#region src/catalogs/root-model-supply.ts
5350
+ /** Steps whose effect a root label can BE. */
5351
+ var LABEL_SUPPLY_STEP_IDS = [
5744
5352
  "animal-classifier",
5745
5353
  "vehicle-classifier",
5746
5354
  "package-detection"
5747
5355
  ];
5748
- /** Narrow a step id to a fillable one — type guard, not a cast. */
5749
- function isFillableStepId(value) {
5750
- return FILLABLE_STEP_IDS.some((id) => id === value);
5356
+ /** Steps whose box a root detection can BE. */
5357
+ var CROP_SUPPLY_STEP_IDS = ["plate-detection", "face-detection"];
5358
+ /** Every step a root model can supply. */
5359
+ var ROOT_SUPPLIABLE_STEP_IDS = [...LABEL_SUPPLY_STEP_IDS, ...CROP_SUPPLY_STEP_IDS];
5360
+ /** Narrow a step id to a suppliable one — type guard, not a cast. */
5361
+ function isRootSuppliableStepId(value) {
5362
+ return ROOT_SUPPLIABLE_STEP_IDS.some((id) => id === value);
5363
+ }
5364
+ /** Narrow a step id to a label-kind one. */
5365
+ function isLabelSupplyStepId(value) {
5366
+ return LABEL_SUPPLY_STEP_IDS.some((id) => id === value);
5751
5367
  }
5752
5368
  /**
5753
- * The EFFECT vocabulary of each fillable step: exactly the strings the step
5369
+ * The EFFECT vocabulary of each label-kind step: exactly the strings the step
5754
5370
  * itself emits, in its own spelling. A linked label is one of these and nothing
5755
5371
  * else, so a tier-1 value means the same thing whichever writer produced it.
5756
5372
  *
5757
5373
  * - `animal-classifier`: the PRIMARY model's `-labels.json` (Open Images V7,
5758
5374
  * 8 classes) — also the species allow-list the step offers.
5759
- * - `vehicle-classifier`: `vehicle-type-v1-labels.json`, capitalised as the
5760
- * model emits them (the classifier writes `winner.class` verbatim).
5375
+ * - `vehicle-classifier`: the classifier's labels, capitalised as it emits them
5376
+ * (it writes `winner.class` verbatim).
5761
5377
  * - `package-detection`: its one output class.
5762
5378
  *
5763
- * `scripts/check-label-link-vocabulary.ts` fails the build if a model entry's
5379
+ * `scripts/check-label-link-vocabulary.ts` fails the build if a declared
5764
5380
  * `labelToEffect` names anything outside this table.
5765
5381
  */
5766
- var FILLABLE_STEP_VOCABULARIES = {
5382
+ var LABEL_SUPPLY_VOCABULARIES = {
5767
5383
  "animal-classifier": [
5768
5384
  "bird",
5769
5385
  "cat",
@@ -5786,8 +5402,8 @@ var FILLABLE_STEP_VOCABULARIES = {
5786
5402
  ],
5787
5403
  "package-detection": ["package"]
5788
5404
  };
5789
- /** The macro a detection must carry for the step to apply to it. */
5790
- var FILLABLE_STEP_MACRO = {
5405
+ /** The macro a detection must carry for a label-kind step to apply to it. */
5406
+ var LABEL_SUPPLY_MACRO = {
5791
5407
  "animal-classifier": "animal",
5792
5408
  "vehicle-classifier": "vehicle",
5793
5409
  "package-detection": "package"
@@ -5804,12 +5420,46 @@ var EFFECT_ALIASES = {
5804
5420
  },
5805
5421
  "package-detection": {}
5806
5422
  };
5807
- /** The policy values of a step's `labelLink` setting. */
5808
- var LABEL_LINK_POLICIES = ["run", "skip-when-filled"];
5809
- /** Absent setting ⇒ this. It changes nothing unless the root model declares a fill. */
5810
- var DEFAULT_LABEL_LINK_POLICY = "skip-when-filled";
5811
- /** The step-settings key the policy is stored under (DeviceStepConfig.settings). */
5812
- var LABEL_LINK_SETTING_KEY = "labelLink";
5423
+ var CROP_SUPPLY_SOURCES = {
5424
+ "plate-detection": {
5425
+ rootLabels: ["license_plate"],
5426
+ parentMacro: "vehicle",
5427
+ childClass: "plate",
5428
+ servedChildSteps: ["plate-ocr"],
5429
+ use: "as-output"
5430
+ },
5431
+ "face-detection": {
5432
+ rootLabels: ["face"],
5433
+ parentMacro: "person",
5434
+ childClass: "face",
5435
+ servedChildSteps: ["face-embedding"],
5436
+ use: "refine",
5437
+ minRootInputPx: 640
5438
+ }
5439
+ };
5440
+ /**
5441
+ * Whether an operator intends a step to take the root's output when the
5442
+ * root declares it — the default of the `useRootModel` flag. The label kinds
5443
+ * default ON: the detector's answer is the cheaper one and the classifier
5444
+ * keeps its model for the day the root changes. The crop kinds default OFF: a
5445
+ * root plate box has an uncalibrated OCR margin, and root-face refinement has
5446
+ * not run on live traffic yet.
5447
+ */
5448
+ var USE_ROOT_MODEL_DEFAULTS = {
5449
+ "animal-classifier": true,
5450
+ "vehicle-classifier": true,
5451
+ "package-detection": true,
5452
+ "plate-detection": false,
5453
+ "face-detection": false
5454
+ };
5455
+ /** The step-settings key the flag is stored under (DeviceStepConfig.settings, camera overrides). */
5456
+ var USE_ROOT_MODEL_SETTING_KEY = "useRootModel";
5457
+ /**
5458
+ * The retired D715 policy key. A `skip-when-filled` / `run` value still
5459
+ * stored under it reads as the flag (`true` / `false`) when no flag is stored
5460
+ * — the normal read path, not a migration.
5461
+ */
5462
+ var RETIRED_LABEL_LINK_KEY = "labelLink";
5813
5463
  /** `ScoredLabel.stepId` prefix of a label the detector wrote for a step. */
5814
5464
  var LINKED_LABEL_STEP_PREFIX = "detector-link:";
5815
5465
  /** `detector-link:<stepId>` — the attribution of a linked label. */
@@ -5821,91 +5471,175 @@ function linkedStepOf(attributionStepId) {
5821
5471
  if (attributionStepId === void 0) return void 0;
5822
5472
  if (!attributionStepId.startsWith("detector-link:")) return void 0;
5823
5473
  const stepId = attributionStepId.slice(14);
5824
- return isFillableStepId(stepId) ? stepId : void 0;
5825
- }
5826
- /**
5827
- * A labelmap is COCO when it carries at least half of the COCO-80 classes. A
5828
- * COCO detector NEVER fills a step (operator decision, D715): its `dog` / `car`
5829
- * is the generic class the classifier exists to refine, and its six animal
5830
- * classes would otherwise read as "fills animal-classifier 6/8". Frigate+
5831
- * shares about a dozen COCO names; a COCO-80 or COCO-91 labelmap carries ~80.
5832
- */
5833
- function isCocoLabelmap(labels) {
5834
- const present = new Set(labels);
5835
- return COCO_80_LABELS.filter((l) => present.has(l.id)).length * 2 >= COCO_80_LABELS.length;
5474
+ return isLabelSupplyStepId(stepId) ? stepId : void 0;
5836
5475
  }
5837
5476
  function effectFor(stepId, label) {
5838
5477
  const alias = EFFECT_ALIASES[stepId][label];
5839
5478
  if (alias !== void 0) return alias;
5840
5479
  const folded = label.toLowerCase();
5841
- return FILLABLE_STEP_VOCABULARIES[stepId].find((v) => v.toLowerCase() === folded);
5480
+ return LABEL_SUPPLY_VOCABULARIES[stepId].find((v) => v.toLowerCase() === folded);
5842
5481
  }
5843
5482
  /**
5844
- * Which steps a root detector fills, from its labelmap and classMap. A label
5845
- * counts for a step only when the model's classMap sends it to that step's
5846
- * macro AND it names a vocabulary entry. A step none of the labels reach is
5847
- * not declared; a COCO labelmap declares nothing.
5483
+ * Which steps a root detector can supply, from its labelmap and classMap.
5484
+ *
5485
+ * - label kind: a label counts for a step only when the classMap sends it to
5486
+ * that step's macro AND it names a vocabulary entry. Every root is judged
5487
+ * the same way — a COCO model supplies the animal classifier with the six
5488
+ * species COCO names, exactly as a Frigate+ model supplies seven.
5489
+ * - crop kind: the labelmap carries one of the step's root labels. Those
5490
+ * labels are deliberately left out of the classMap, so they never make a
5491
+ * track of their own.
5492
+ *
5493
+ * No classMap ⇒ no label supply (nothing says which macro a label lives under).
5848
5494
  */
5849
- function deriveClassifierFills(labels, classMap) {
5850
- if (classMap === void 0 || isCocoLabelmap(labels)) return [];
5851
- const fills = [];
5852
- for (const stepId of FILLABLE_STEP_IDS) {
5495
+ function deriveRootSupplies(labels, classMap) {
5496
+ const supplies = [];
5497
+ if (classMap !== void 0) for (const stepId of LABEL_SUPPLY_STEP_IDS) {
5853
5498
  const labelToEffect = {};
5854
5499
  for (const label of labels) {
5855
- if (classMap.mapping[label] !== FILLABLE_STEP_MACRO[stepId]) continue;
5500
+ if (classMap.mapping[label] !== LABEL_SUPPLY_MACRO[stepId]) continue;
5856
5501
  const effect = effectFor(stepId, label);
5857
5502
  if (effect !== void 0) labelToEffect[label] = effect;
5858
5503
  }
5859
5504
  const covered = new Set(Object.values(labelToEffect));
5860
5505
  if (covered.size === 0) continue;
5861
- const uncovered = FILLABLE_STEP_VOCABULARIES[stepId].filter((v) => !covered.has(v));
5862
- fills.push({
5506
+ const uncovered = LABEL_SUPPLY_VOCABULARIES[stepId].filter((v) => !covered.has(v));
5507
+ supplies.push({
5508
+ kind: "label",
5863
5509
  stepId,
5864
5510
  labelToEffect,
5865
5511
  uncovered
5866
5512
  });
5867
5513
  }
5868
- return fills;
5869
- }
5870
- /** The fill a model declares for one step, if any. */
5871
- function fillFor(entry, stepId) {
5872
- return entry?.fillsClassifierEffects?.find((f) => f.stepId === stepId);
5873
- }
5874
- /** Read the `labelLink` policy off a step's settings bag; anything else ⇒ the default. */
5875
- function readLabelLinkPolicy(settings) {
5876
- const raw = settings?.[LABEL_LINK_SETTING_KEY];
5877
- return LABEL_LINK_POLICIES.find((p) => p === raw) ?? "skip-when-filled";
5878
- }
5879
- /**
5880
- * Decide the writer of one filled effect for one camera.
5881
- *
5882
- * - The step is not running (disabled, or not in the camera's tree): the
5883
- * detector is the only writer — authoritative, nothing to skip.
5884
- * - The step runs, the policy is `skip-when-filled` and every coverage gap is
5885
- * switched off in `enabledClasses`: the detector is authoritative and the
5886
- * step is skipped.
5887
- * - Otherwise the step runs and is the writer; the linked label is a score-0
5888
- * fallback.
5889
- */
5890
- function resolveLabelLink(fill, step) {
5891
- const policy = readLabelLinkPolicy(step?.settings);
5892
- const rawEnabled = step?.settings?.["enabledClasses"];
5893
- const allowList = Array.isArray(rawEnabled) && rawEnabled.length > 0 ? rawEnabled.filter((v) => typeof v === "string") : null;
5894
- const openGaps = fill.uncovered.filter((g) => allowList === null || allowList.includes(g));
5895
- if (step === void 0 || !step.enabled) return {
5896
- authoritative: true,
5897
- skip: false,
5898
- policy,
5899
- openGaps
5900
- };
5901
- const skip = policy === "skip-when-filled" && openGaps.length === 0;
5514
+ const present = new Set(labels);
5515
+ for (const stepId of CROP_SUPPLY_STEP_IDS) {
5516
+ const source = CROP_SUPPLY_SOURCES[stepId];
5517
+ const rootLabels = source.rootLabels.filter((l) => present.has(l));
5518
+ if (rootLabels.length === 0) continue;
5519
+ supplies.push({
5520
+ kind: "crop",
5521
+ stepId,
5522
+ rootLabels,
5523
+ parentMacro: source.parentMacro,
5524
+ childClass: source.childClass
5525
+ });
5526
+ }
5527
+ return supplies;
5528
+ }
5529
+ /**
5530
+ * The supplies a root model declares. A row registered with a declaration
5531
+ * carries it (`suppliesSteps`, computed at import from the model's own
5532
+ * labelmap); a row without one — a built-in entry, or a custom row registered
5533
+ * before the field existed — is derived here, on read, from the same inputs.
5534
+ */
5535
+ function rootSuppliesOf(entry, stepDefaults) {
5536
+ const declared = entry?.suppliesSteps ?? deriveRootSupplies(entry !== void 0 && entry.labels.length > 0 ? entry.labels.map((l) => l.id) : stepDefaults.labels, entry?.classMap ?? stepDefaults.classMap);
5537
+ const inputPx = entry !== void 0 ? Math.min(entry.inputSize.width, entry.inputSize.height) : void 0;
5538
+ if (inputPx === void 0) return declared;
5539
+ return declared.map((s) => s.kind === "crop" ? {
5540
+ ...s,
5541
+ rootInputPx: inputPx
5542
+ } : s);
5543
+ }
5544
+ /** The supply a root declares for one step, if any. */
5545
+ function supplyFor(supplies, stepId) {
5546
+ return supplies?.find((s) => s.stepId === stepId);
5547
+ }
5548
+ /**
5549
+ * Read the `useRootModel` flag off a step's settings bag. Absent ⇒ the
5550
+ * retired `labelLink` value if one is stored, else the step's default.
5551
+ */
5552
+ function readUseRootModel(stepId, settings) {
5553
+ const raw = settings?.[USE_ROOT_MODEL_SETTING_KEY];
5554
+ if (typeof raw === "boolean") return raw;
5555
+ const retired = settings?.[RETIRED_LABEL_LINK_KEY];
5556
+ if (retired === "skip-when-filled") return true;
5557
+ if (retired === "run") return false;
5558
+ return USE_ROOT_MODEL_DEFAULTS[stepId];
5559
+ }
5560
+ /** Why a DECLARED supply is still not usable, or `undefined` when it is. */
5561
+ function supplyBlocker(supply) {
5562
+ if (supply.kind !== "crop") return void 0;
5563
+ const min = CROP_SUPPLY_SOURCES[supply.stepId].minRootInputPx;
5564
+ if (min === void 0) return void 0;
5565
+ return supply.rootInputPx !== void 0 && supply.rootInputPx >= min ? void 0 : "root-input-too-small";
5566
+ }
5567
+ /**
5568
+ * THE decision. Effective = the operator intends it AND the current root
5569
+ * declares it. It never looks at, changes or clears the step's `modelId`: a
5570
+ * root that cannot supply the step leaves the step running its own model, and
5571
+ * switching back to a root that can re-activates the supply by itself.
5572
+ */
5573
+ function resolveRootSupply(stepId, settings, rootSupplies) {
5574
+ const supply = supplyFor(rootSupplies, stepId);
5575
+ const intent = readUseRootModel(stepId, settings);
5576
+ const blocker = supply === void 0 ? "root-does-not-declare" : supplyBlocker(supply);
5902
5577
  return {
5903
- authoritative: skip,
5904
- skip,
5905
- policy,
5906
- openGaps
5578
+ stepId,
5579
+ supply,
5580
+ intent,
5581
+ effective: intent && blocker === void 0,
5582
+ inactive: intent && blocker !== void 0,
5583
+ ...intent && blocker !== void 0 ? { inactiveReason: blocker } : {}
5907
5584
  };
5908
5585
  }
5586
+ /**
5587
+ * The fine label a supplied root class becomes for a step whose supply is
5588
+ * effective, or `undefined` when the step's `enabledClasses` switched it off —
5589
+ * the detection then stays at its macro (`animal`). Empty / absent allow-list
5590
+ * = every class.
5591
+ */
5592
+ function allowedSuppliedEffect(effect, settings) {
5593
+ const raw = settings?.["enabledClasses"];
5594
+ if (!Array.isArray(raw) || raw.length === 0) return true;
5595
+ return raw.some((v) => v === effect);
5596
+ }
5597
+ /** The child steps of a crop-kind step that still run on the root's box. */
5598
+ function rootSupplyServes(stepId) {
5599
+ return CROP_SUPPLY_SOURCES[stepId].servedChildSteps;
5600
+ }
5601
+ /** Minimum fraction of a child box's area that must lie inside its parent. */
5602
+ var ROOT_CHILD_CONTAINMENT_MIN = .9;
5603
+ /**
5604
+ * The parent a root child box belongs to: among `parents`, the SMALLEST whose
5605
+ * box holds at least {@link ROOT_CHILD_CONTAINMENT_MIN} of the child's area
5606
+ * (a plate inside the car, not inside the bus behind it). `-1` when none does
5607
+ * — the box then belongs to nobody and makes nothing.
5608
+ */
5609
+ function containingParentIndex(child, parents) {
5610
+ const childArea = child.w * child.h;
5611
+ if (!(childArea > 0)) return -1;
5612
+ let best = -1;
5613
+ let bestArea = Number.POSITIVE_INFINITY;
5614
+ parents.forEach((p, i) => {
5615
+ if (Math.max(0, Math.min(child.x + child.w, p.x + p.w) - Math.max(child.x, p.x)) * Math.max(0, Math.min(child.y + child.h, p.y + p.h) - Math.max(child.y, p.y)) / childArea < .9) return;
5616
+ const area = p.w * p.h;
5617
+ if (area < bestArea) {
5618
+ best = i;
5619
+ bestArea = area;
5620
+ }
5621
+ });
5622
+ return best;
5623
+ }
5624
+ var SUPPLY_NOUN = {
5625
+ "animal-classifier": "animals",
5626
+ "vehicle-classifier": "vehicles",
5627
+ "package-detection": "packages",
5628
+ "plate-detection": "plates",
5629
+ "face-detection": "faces"
5630
+ };
5631
+ /** One short phrase per supply — `animals 6/8`, `plates`. */
5632
+ function describeRootSupply(supply) {
5633
+ const noun = SUPPLY_NOUN[supply.stepId];
5634
+ if (supply.kind === "crop") return noun;
5635
+ const total = LABEL_SUPPLY_VOCABULARIES[supply.stepId].length;
5636
+ if (total <= 1) return noun;
5637
+ return `${noun} ${String(total - supply.uncovered.length)}/${String(total)}`;
5638
+ }
5639
+ /** `animals 6/8 · vehicles 5/8 · plates · faces` — empty string for none. */
5640
+ function describeRootSupplies(supplies) {
5641
+ return (supplies ?? []).map(describeRootSupply).join(" · ");
5642
+ }
5909
5643
  //#endregion
5910
5644
  //#region src/types/models.ts
5911
5645
  var MODEL_FORMATS = [
@@ -6062,12 +5796,35 @@ var ModelLicenseRecordSchema = zod.z.object({
6062
5796
  * `camstack/docs` → `/docs/detection/models`.
6063
5797
  */
6064
5798
  var ModelLicenseSchema = zod.z.preprocess((value) => typeof value === "string" ? { weights: value } : value, ModelLicenseRecordSchema);
6065
- /** One `fillsClassifierEffects` entry — see `ModelCatalogEntry.fillsClassifierEffects`. */
6066
- var FillsClassifierEffectSchema = zod.z.object({
6067
- stepId: zod.z.enum(FILLABLE_STEP_IDS),
5799
+ /**
5800
+ * One step a ROOT detector can supply from its own output (D730) — see
5801
+ * `ModelCatalogEntry.suppliesSteps`.
5802
+ *
5803
+ * - `label`: the root's raw class IS the step's answer. `labelToEffect` maps
5804
+ * the root's label to the step's vocabulary; `uncovered` is the vocabulary
5805
+ * the root cannot produce (shown as unavailable, never a blocker).
5806
+ * - `crop`: the root draws the box the step would have found (`license_plate`
5807
+ * for plate-detection, `face` for face-detection). The box becomes a detail
5808
+ * child of the `parentMacro` detection that contains it — never a track.
5809
+ */
5810
+ var RootStepSupplySchema = zod.z.discriminatedUnion("kind", [zod.z.object({
5811
+ kind: zod.z.literal("label"),
5812
+ stepId: zod.z.enum(LABEL_SUPPLY_STEP_IDS),
6068
5813
  labelToEffect: zod.z.record(zod.z.string(), zod.z.string()),
6069
5814
  uncovered: zod.z.array(zod.z.string()).readonly()
6070
- });
5815
+ }), zod.z.object({
5816
+ kind: zod.z.literal("crop"),
5817
+ stepId: zod.z.enum(CROP_SUPPLY_STEP_IDS),
5818
+ rootLabels: zod.z.array(zod.z.string()).readonly(),
5819
+ parentMacro: zod.z.enum(["vehicle", "person"]),
5820
+ childClass: zod.z.enum(["plate", "face"]),
5821
+ /**
5822
+ * The root's smaller input side, stamped on read by `rootSuppliesOf` from
5823
+ * the model entry — what a step's `minRootInputPx` gate judges. Never
5824
+ * stored by an import.
5825
+ */
5826
+ rootInputPx: zod.z.number().int().positive().optional()
5827
+ })]);
6071
5828
  var ModelCatalogEntrySchema = zod.z.object({
6072
5829
  id: zod.z.string(),
6073
5830
  name: zod.z.string(),
@@ -6194,15 +5951,15 @@ var ModelCatalogEntrySchema = zod.z.object({
6194
5951
  */
6195
5952
  classMap: DetectionCatalogClassMapSchema.optional(),
6196
5953
  /**
6197
- * The pipeline steps this ROOT detector already does the work of (D715):
6198
- * its labels name the effect the step exists to produce (`deer` for
6199
- * `animal-classifier`, `package` for `package-detection`). Derived from the
6200
- * labelmap by `deriveClassifierFills`, never hand-written; a COCO model
6201
- * declares none. Whether a declaration is honoured is the step's own
6202
- * `labelLink` policy (`resolveLabelLink`). `labelToEffect` values are in
6203
- * `FILLABLE_STEP_VOCABULARIES` (guard `check-label-link-vocabulary`).
5954
+ * The pipeline steps this ROOT detector can supply from its own output
5955
+ * (D730): its labels name a step's effect (`deer` for `animal-classifier`)
5956
+ * or draw a step's box (`license_plate` for `plate-detection`). Computed at
5957
+ * import from THIS model's labelmap by `deriveRootSupplies`, never written
5958
+ * by hand and never assumed per family; a row without it is derived on read
5959
+ * (`rootSuppliesOf`). Whether a camera uses it is the step's own
5960
+ * `useRootModel` flag (`resolveRootSupply`).
6204
5961
  */
6205
- fillsClassifierEffects: zod.z.array(FillsClassifierEffectSchema).readonly().optional(),
5962
+ suppliesSteps: zod.z.array(RootStepSupplySchema).readonly().optional(),
6206
5963
  /**
6207
5964
  * The model's CLIP feature-space contract (text encoder, dimension, vector
6208
5965
  * index, token window, search floor) — see `clip-model.ts`. Present ONLY on a
@@ -10995,7 +10752,7 @@ function unavailableFor(tf, role, mode, cap, at) {
10995
10752
  };
10996
10753
  return {
10997
10754
  ok: false,
10998
- problem: problem("not-replaceable", at, `\`${cap}.${tf.path}\` reads a source but can say neither null nor 'unknown', and an ADDED capability has no native reading to fall back to (D393, D663)`)
10755
+ problem: problem("not-replaceable", at, `\`${cap}.${tf.path}\` reads a source but can say neither null nor 'unknown', and an ADDED capability has no native reading to fall back to`)
10999
10756
  };
11000
10757
  }
11001
10758
  //#endregion
@@ -16359,6 +16116,151 @@ var filesystemBrowseCapability = {
16359
16116
  }
16360
16117
  };
16361
16118
  //#endregion
16119
+ //#region src/capabilities/hub-address.ts
16120
+ var IPV4_LITERAL = /^\d{1,3}(?:\.\d{1,3}){3}$/;
16121
+ function hostnameOf(baseUrl) {
16122
+ try {
16123
+ const host = new URL(baseUrl).hostname;
16124
+ return host.length > 0 ? host : null;
16125
+ } catch {
16126
+ return null;
16127
+ }
16128
+ }
16129
+ function isMesh(endpoint) {
16130
+ return endpoint.kind === "public" && endpoint.interfaceKind === "vpn";
16131
+ }
16132
+ function isTunnel(endpoint) {
16133
+ return endpoint.kind === "public" && endpoint.interfaceKind === "public";
16134
+ }
16135
+ function isPlausibleLan(endpoint) {
16136
+ return (endpoint.kind === "lan-ipv4" || endpoint.kind === "lan-ipv6") && endpoint.plausible;
16137
+ }
16138
+ function isLanIpv4Literal(endpoint) {
16139
+ if (endpoint.kind !== "lan-ipv4" || !endpoint.plausible) return false;
16140
+ const host = hostnameOf(endpoint.baseUrl);
16141
+ return host !== null && IPV4_LITERAL.test(host);
16142
+ }
16143
+ /** Lower = better; `null` = never this audience's answer. */
16144
+ function rankFor(audience, endpoint) {
16145
+ if (endpoint.kind === "loopback" || endpoint.kind === "app-link") return null;
16146
+ if (hostnameOf(endpoint.baseUrl) === null) return null;
16147
+ if (audience === "cluster") {
16148
+ if (isLanIpv4Literal(endpoint)) return 0;
16149
+ if (isPlausibleLan(endpoint)) return 1;
16150
+ if (isMesh(endpoint)) return 2;
16151
+ return null;
16152
+ }
16153
+ if (isTunnel(endpoint)) return 0;
16154
+ if (isMesh(endpoint)) return 1;
16155
+ if (isLanIpv4Literal(endpoint)) return 2;
16156
+ if (isPlausibleLan(endpoint)) return 3;
16157
+ return null;
16158
+ }
16159
+ var LOOPBACK_HOSTS = new Set([
16160
+ "localhost",
16161
+ "0.0.0.0",
16162
+ "::1",
16163
+ "[::1]",
16164
+ "::",
16165
+ "[::]"
16166
+ ]);
16167
+ function isLoopbackHost(hostname) {
16168
+ const h = hostname.toLowerCase();
16169
+ if (LOOPBACK_HOSTS.has(h) || h.endsWith(".localhost")) return true;
16170
+ return /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(h);
16171
+ }
16172
+ /**
16173
+ * Validate an operator-typed override: an http(s) URL with a host, no
16174
+ * credentials, no path, and never loopback (it would name whoever dials it).
16175
+ * Answers the normalised origin (`scheme://host[:port]`).
16176
+ */
16177
+ function validateHubAddressOverride(raw) {
16178
+ const trimmed = raw.trim();
16179
+ if (trimmed === "") return {
16180
+ ok: false,
16181
+ reason: "Enter an address, e.g. https://192.168.1.50:4443."
16182
+ };
16183
+ let parsed;
16184
+ try {
16185
+ parsed = new URL(trimmed);
16186
+ } catch {
16187
+ return {
16188
+ ok: false,
16189
+ reason: "Not a URL — include http:// or https://."
16190
+ };
16191
+ }
16192
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:") return {
16193
+ ok: false,
16194
+ reason: "Use an http:// or https:// address."
16195
+ };
16196
+ if (parsed.username !== "" || parsed.password !== "") return {
16197
+ ok: false,
16198
+ reason: "The address must not carry a user name or password."
16199
+ };
16200
+ if (parsed.hostname === "") return {
16201
+ ok: false,
16202
+ reason: "The address has no host."
16203
+ };
16204
+ if (isLoopbackHost(parsed.hostname)) return {
16205
+ ok: false,
16206
+ reason: "A loopback address names whoever dials it, never this hub — use an address other machines reach."
16207
+ };
16208
+ if (parsed.pathname !== "/" || parsed.search !== "" || parsed.hash !== "") return {
16209
+ ok: false,
16210
+ reason: "Enter only the address (scheme, host and port), without a path."
16211
+ };
16212
+ return {
16213
+ ok: true,
16214
+ baseUrl: parsed.origin
16215
+ };
16216
+ }
16217
+ /**
16218
+ * The hub's base URL for `audience`, without a trailing slash, or `null` when
16219
+ * the palette holds nothing that audience can reach. A valid operator
16220
+ * `override` wins outright; an empty one means automatic. Ties inside a rank
16221
+ * go to the palette's own `priority` (its preferred interface first).
16222
+ */
16223
+ function pickHubBaseUrl(endpoints, audience, override = null) {
16224
+ return resolveHubAddress(endpoints, audience, override).resolved;
16225
+ }
16226
+ /** {@link pickHubBaseUrl}, saying where the answer came from. */
16227
+ function resolveHubAddress(endpoints, audience, override) {
16228
+ if (override !== null && override !== "") {
16229
+ const check = validateHubAddressOverride(override);
16230
+ if (check.ok) return {
16231
+ override,
16232
+ resolved: check.baseUrl,
16233
+ source: "override"
16234
+ };
16235
+ }
16236
+ const auto = pickFromPalette(endpoints, audience);
16237
+ return {
16238
+ override: override === null || override === "" ? null : override,
16239
+ resolved: auto,
16240
+ source: auto === null ? "none" : "auto"
16241
+ };
16242
+ }
16243
+ function pickFromPalette(endpoints, audience) {
16244
+ const best = endpoints.flatMap((endpoint) => {
16245
+ const rank = rankFor(audience, endpoint);
16246
+ return rank === null ? [] : [{
16247
+ rank,
16248
+ priority: endpoint.priority,
16249
+ endpoint
16250
+ }];
16251
+ }).toSorted((a, b) => a.rank - b.rank || a.priority - b.priority)[0];
16252
+ return best === void 0 ? null : best.endpoint.baseUrl.replace(/\/+$/, "");
16253
+ }
16254
+ /** The bare hostname of {@link pickHubBaseUrl}'s answer, or `null`. */
16255
+ function pickHubHostname(endpoints, audience, override = null) {
16256
+ const baseUrl = pickHubBaseUrl(endpoints, audience, override);
16257
+ return baseUrl === null ? null : hostnameOf(baseUrl);
16258
+ }
16259
+ /** The bare hostname of a base URL, or `null` when it does not parse. */
16260
+ function hubAddressHostname(baseUrl) {
16261
+ return baseUrl === null ? null : hostnameOf(baseUrl);
16262
+ }
16263
+ //#endregion
16362
16264
  //#region src/capabilities/ai-cap-timeouts.ts
16363
16265
  /**
16364
16266
  * Transport bounds for AI capability methods.
@@ -18591,6 +18493,398 @@ var notificationOutputCapability = {
18591
18493
  }
18592
18494
  };
18593
18495
  //#endregion
18496
+ //#region src/catalogs/coco-classmap.ts
18497
+ var COCO_80_LABELS = [
18498
+ {
18499
+ id: "person",
18500
+ name: "Person"
18501
+ },
18502
+ {
18503
+ id: "bicycle",
18504
+ name: "Bicycle"
18505
+ },
18506
+ {
18507
+ id: "car",
18508
+ name: "Car"
18509
+ },
18510
+ {
18511
+ id: "motorcycle",
18512
+ name: "Motorcycle"
18513
+ },
18514
+ {
18515
+ id: "airplane",
18516
+ name: "Airplane"
18517
+ },
18518
+ {
18519
+ id: "bus",
18520
+ name: "Bus"
18521
+ },
18522
+ {
18523
+ id: "train",
18524
+ name: "Train"
18525
+ },
18526
+ {
18527
+ id: "truck",
18528
+ name: "Truck"
18529
+ },
18530
+ {
18531
+ id: "boat",
18532
+ name: "Boat"
18533
+ },
18534
+ {
18535
+ id: "traffic light",
18536
+ name: "Traffic Light"
18537
+ },
18538
+ {
18539
+ id: "fire hydrant",
18540
+ name: "Fire Hydrant"
18541
+ },
18542
+ {
18543
+ id: "stop sign",
18544
+ name: "Stop Sign"
18545
+ },
18546
+ {
18547
+ id: "parking meter",
18548
+ name: "Parking Meter"
18549
+ },
18550
+ {
18551
+ id: "bench",
18552
+ name: "Bench"
18553
+ },
18554
+ {
18555
+ id: "bird",
18556
+ name: "Bird"
18557
+ },
18558
+ {
18559
+ id: "cat",
18560
+ name: "Cat"
18561
+ },
18562
+ {
18563
+ id: "dog",
18564
+ name: "Dog"
18565
+ },
18566
+ {
18567
+ id: "horse",
18568
+ name: "Horse"
18569
+ },
18570
+ {
18571
+ id: "sheep",
18572
+ name: "Sheep"
18573
+ },
18574
+ {
18575
+ id: "cow",
18576
+ name: "Cow"
18577
+ },
18578
+ {
18579
+ id: "elephant",
18580
+ name: "Elephant"
18581
+ },
18582
+ {
18583
+ id: "bear",
18584
+ name: "Bear"
18585
+ },
18586
+ {
18587
+ id: "zebra",
18588
+ name: "Zebra"
18589
+ },
18590
+ {
18591
+ id: "giraffe",
18592
+ name: "Giraffe"
18593
+ },
18594
+ {
18595
+ id: "backpack",
18596
+ name: "Backpack"
18597
+ },
18598
+ {
18599
+ id: "umbrella",
18600
+ name: "Umbrella"
18601
+ },
18602
+ {
18603
+ id: "handbag",
18604
+ name: "Handbag"
18605
+ },
18606
+ {
18607
+ id: "tie",
18608
+ name: "Tie"
18609
+ },
18610
+ {
18611
+ id: "suitcase",
18612
+ name: "Suitcase"
18613
+ },
18614
+ {
18615
+ id: "frisbee",
18616
+ name: "Frisbee"
18617
+ },
18618
+ {
18619
+ id: "skis",
18620
+ name: "Skis"
18621
+ },
18622
+ {
18623
+ id: "snowboard",
18624
+ name: "Snowboard"
18625
+ },
18626
+ {
18627
+ id: "sports ball",
18628
+ name: "Sports Ball"
18629
+ },
18630
+ {
18631
+ id: "kite",
18632
+ name: "Kite"
18633
+ },
18634
+ {
18635
+ id: "baseball bat",
18636
+ name: "Baseball Bat"
18637
+ },
18638
+ {
18639
+ id: "baseball glove",
18640
+ name: "Baseball Glove"
18641
+ },
18642
+ {
18643
+ id: "skateboard",
18644
+ name: "Skateboard"
18645
+ },
18646
+ {
18647
+ id: "surfboard",
18648
+ name: "Surfboard"
18649
+ },
18650
+ {
18651
+ id: "tennis racket",
18652
+ name: "Tennis Racket"
18653
+ },
18654
+ {
18655
+ id: "bottle",
18656
+ name: "Bottle"
18657
+ },
18658
+ {
18659
+ id: "wine glass",
18660
+ name: "Wine Glass"
18661
+ },
18662
+ {
18663
+ id: "cup",
18664
+ name: "Cup"
18665
+ },
18666
+ {
18667
+ id: "fork",
18668
+ name: "Fork"
18669
+ },
18670
+ {
18671
+ id: "knife",
18672
+ name: "Knife"
18673
+ },
18674
+ {
18675
+ id: "spoon",
18676
+ name: "Spoon"
18677
+ },
18678
+ {
18679
+ id: "bowl",
18680
+ name: "Bowl"
18681
+ },
18682
+ {
18683
+ id: "banana",
18684
+ name: "Banana"
18685
+ },
18686
+ {
18687
+ id: "apple",
18688
+ name: "Apple"
18689
+ },
18690
+ {
18691
+ id: "sandwich",
18692
+ name: "Sandwich"
18693
+ },
18694
+ {
18695
+ id: "orange",
18696
+ name: "Orange"
18697
+ },
18698
+ {
18699
+ id: "broccoli",
18700
+ name: "Broccoli"
18701
+ },
18702
+ {
18703
+ id: "carrot",
18704
+ name: "Carrot"
18705
+ },
18706
+ {
18707
+ id: "hot dog",
18708
+ name: "Hot Dog"
18709
+ },
18710
+ {
18711
+ id: "pizza",
18712
+ name: "Pizza"
18713
+ },
18714
+ {
18715
+ id: "donut",
18716
+ name: "Donut"
18717
+ },
18718
+ {
18719
+ id: "cake",
18720
+ name: "Cake"
18721
+ },
18722
+ {
18723
+ id: "chair",
18724
+ name: "Chair"
18725
+ },
18726
+ {
18727
+ id: "couch",
18728
+ name: "Couch"
18729
+ },
18730
+ {
18731
+ id: "potted plant",
18732
+ name: "Potted Plant"
18733
+ },
18734
+ {
18735
+ id: "bed",
18736
+ name: "Bed"
18737
+ },
18738
+ {
18739
+ id: "dining table",
18740
+ name: "Dining Table"
18741
+ },
18742
+ {
18743
+ id: "toilet",
18744
+ name: "Toilet"
18745
+ },
18746
+ {
18747
+ id: "tv",
18748
+ name: "TV"
18749
+ },
18750
+ {
18751
+ id: "laptop",
18752
+ name: "Laptop"
18753
+ },
18754
+ {
18755
+ id: "mouse",
18756
+ name: "Mouse"
18757
+ },
18758
+ {
18759
+ id: "remote",
18760
+ name: "Remote"
18761
+ },
18762
+ {
18763
+ id: "keyboard",
18764
+ name: "Keyboard"
18765
+ },
18766
+ {
18767
+ id: "cell phone",
18768
+ name: "Cell Phone"
18769
+ },
18770
+ {
18771
+ id: "microwave",
18772
+ name: "Microwave"
18773
+ },
18774
+ {
18775
+ id: "oven",
18776
+ name: "Oven"
18777
+ },
18778
+ {
18779
+ id: "toaster",
18780
+ name: "Toaster"
18781
+ },
18782
+ {
18783
+ id: "sink",
18784
+ name: "Sink"
18785
+ },
18786
+ {
18787
+ id: "refrigerator",
18788
+ name: "Refrigerator"
18789
+ },
18790
+ {
18791
+ id: "book",
18792
+ name: "Book"
18793
+ },
18794
+ {
18795
+ id: "clock",
18796
+ name: "Clock"
18797
+ },
18798
+ {
18799
+ id: "vase",
18800
+ name: "Vase"
18801
+ },
18802
+ {
18803
+ id: "scissors",
18804
+ name: "Scissors"
18805
+ },
18806
+ {
18807
+ id: "teddy bear",
18808
+ name: "Teddy Bear"
18809
+ },
18810
+ {
18811
+ id: "hair drier",
18812
+ name: "Hair Drier"
18813
+ },
18814
+ {
18815
+ id: "toothbrush",
18816
+ name: "Toothbrush"
18817
+ }
18818
+ ];
18819
+ var MACRO_LABELS = [
18820
+ {
18821
+ id: "person",
18822
+ name: "Person"
18823
+ },
18824
+ {
18825
+ id: "vehicle",
18826
+ name: "Vehicle"
18827
+ },
18828
+ {
18829
+ id: "animal",
18830
+ name: "Animal"
18831
+ },
18832
+ {
18833
+ id: "package",
18834
+ name: "Package"
18835
+ }
18836
+ ];
18837
+ /**
18838
+ * The class names a per-class COUNT can ever be keyed on — the macro ids, and
18839
+ * only those.
18840
+ *
18841
+ * `preserveOriginal: false` below is the whole reason this set exists: the
18842
+ * executor maps each raw COCO label onto its macro and DROPS everything else,
18843
+ * so a tracked detection's `className` is always one of {@link MACRO_LABELS}.
18844
+ * Any surface that indexes counts by class name — the ZoneAnalytics occupancy
18845
+ * snapshot's `byClass`, and therefore every occupancy rule — can match nothing
18846
+ * else. Derived from the catalog, never hand-listed, so a new macro joins it by
18847
+ * being declared once.
18848
+ *
18849
+ * Cost of not having it, 2026-08-12: the notification rule editor offered the
18850
+ * full taxonomy for an occupancy class (occupancy is the one condition that
18851
+ * does not go through the engine's macro-expanding `expandClassSelector`), two
18852
+ * live rules were authored on `car`, and both counters read 0 forever.
18853
+ */
18854
+ var DETECTION_MACRO_CLASSES = new Set(MACRO_LABELS.map((l) => l.id));
18855
+ /** True when `className` is a macro the detector can actually emit (and hence a
18856
+ * class a count can be keyed on) — see {@link DETECTION_MACRO_CLASSES}. */
18857
+ function isDetectionMacroClass(className) {
18858
+ return DETECTION_MACRO_CLASSES.has(className.trim().toLowerCase());
18859
+ }
18860
+ var COCO_TO_MACRO = {
18861
+ mapping: {
18862
+ person: "person",
18863
+ bicycle: "vehicle",
18864
+ car: "vehicle",
18865
+ motorcycle: "vehicle",
18866
+ airplane: "vehicle",
18867
+ bus: "vehicle",
18868
+ train: "vehicle",
18869
+ truck: "vehicle",
18870
+ boat: "vehicle",
18871
+ bird: "animal",
18872
+ cat: "animal",
18873
+ dog: "animal",
18874
+ horse: "animal",
18875
+ sheep: "animal",
18876
+ cow: "animal",
18877
+ elephant: "animal",
18878
+ bear: "animal",
18879
+ zebra: "animal",
18880
+ giraffe: "animal",
18881
+ suitcase: "package",
18882
+ backpack: "package",
18883
+ handbag: "package"
18884
+ },
18885
+ preserveOriginal: false
18886
+ };
18887
+ //#endregion
18594
18888
  //#region src/catalogs/audio-classmap.ts
18595
18889
  var AUDIO_MACRO_LABELS = [
18596
18890
  {
@@ -21248,7 +21542,7 @@ var NC_CONDITION_CATALOG = [
21248
21542
  operator: "in",
21249
21543
  appliesTo: ["immediate", "track-end"],
21250
21544
  phase: "P1",
21251
- description: "Only recognised people. Selecting NOBODY means every identity in the face gallery; selecting some narrows to those. Matched on the gallery id, so renaming a person does not break the rule. On Immediate delivery the name must already be known when an event is written — choose Immediate, grouped to wait for it (D692)."
21545
+ description: "Only recognised people. Selecting NOBODY means every identity in the face gallery; selecting some narrows to those. Matched on the gallery id, so renaming a person does not break the rule. On Immediate delivery the name must already be known when an event is written — choose Immediate, grouped to wait for it."
21252
21546
  },
21253
21547
  {
21254
21548
  id: "plates",
@@ -25848,6 +26142,34 @@ var pipelineAnalyticsCapability = {
25848
26142
  //#endregion
25849
26143
  //#region src/capabilities/pipeline-executor.cap.ts
25850
26144
  /**
26145
+ * A root model's boxes standing in for one crop-kind step's own inference
26146
+ * (D730) — see `runPipeline.suppliedRoot`.
26147
+ */
26148
+ var SuppliedRootOutputSchema = zod.z.object({
26149
+ stepId: zod.z.string(),
26150
+ /** The root model that drew the boxes — stamped on the result. */
26151
+ modelId: zod.z.string(),
26152
+ detections: zod.z.array(zod.z.object({
26153
+ /** `[x1, y1, x2, y2]` in the pixels of the call's image. */
26154
+ bbox: zod.z.tuple([
26155
+ zod.z.number(),
26156
+ zod.z.number(),
26157
+ zod.z.number(),
26158
+ zod.z.number()
26159
+ ]),
26160
+ score: zod.z.number(),
26161
+ /**
26162
+ * Five facial landmarks in the same pixels — a face the step's own
26163
+ * detector already re-found inside a root face box (D730), so its
26164
+ * embedder child aligns it exactly as it aligns any detected face.
26165
+ */
26166
+ landmarks: zod.z.array(zod.z.object({
26167
+ x: zod.z.number(),
26168
+ y: zod.z.number()
26169
+ })).optional()
26170
+ })).min(1)
26171
+ });
26172
+ /**
25851
26173
  * Reference to the frame's retained NATIVE surface + the parent crop's placement
25852
26174
  * within the frame, so the executor can re-cut a leaf child ROI at native
25853
26175
  * resolution on the detail plane. See the `runPipeline` `nativeCropRef` field.
@@ -25979,7 +26301,7 @@ var PipelineModelOptionSchema = zod.z.object({
25979
26301
  legacy: zod.z.boolean().optional(),
25980
26302
  provider: ModelProviderIdSchema.optional(),
25981
26303
  defaultConfidence: zod.z.number().optional(),
25982
- fillsClassifierEffects: zod.z.array(FillsClassifierEffectSchema).readonly().optional()
26304
+ suppliesSteps: zod.z.array(RootStepSupplySchema).readonly().optional()
25983
26305
  });
25984
26306
  var ConfigFieldBridge = zod.z.custom();
25985
26307
  var PipelineAddonSchemaSchema = zod.z.object({
@@ -26383,7 +26705,16 @@ var pipelineExecutorCapability = {
26383
26705
  * `device-not-servable`), and nothing reaches the camera's live
26384
26706
  * trace stream. Absent ⇒ unchanged behaviour.
26385
26707
  */
26386
- replay: zod.z.literal(true).optional()
26708
+ replay: zod.z.literal(true).optional(),
26709
+ /**
26710
+ * Root-supplied detections for the tree's ROOT step (D730). Set by
26711
+ * `runDetailSubtree` when the camera's root model supplies a crop-kind
26712
+ * step (a Frigate+ `license_plate` for `plate-detection`): the step is
26713
+ * NOT inferred, these boxes are its output, and its children (the plate
26714
+ * reader) run on them through their own crop policy. Boxes are in the
26715
+ * PIXELS of the image this call carries. Absent ⇒ the root step runs.
26716
+ */
26717
+ suppliedRoot: SuppliedRootOutputSchema.optional()
26387
26718
  }), PipelineRunResultBridge, { kind: "mutation" }),
26388
26719
  /**
26389
26720
  * Batched run — N raw frames packed into one cap call. The provider
@@ -27896,7 +28227,22 @@ var pipelineRunnerCapability = {
27896
28227
  */
27897
28228
  cropJpeg: zod.z.string().optional(),
27898
28229
  parent: DetailParentSchema,
27899
- steps: zod.z.array(zod.z.string()).optional()
28230
+ steps: zod.z.array(zod.z.string()).optional(),
28231
+ /**
28232
+ * The camera's root model already drew this step's boxes (D730): a
28233
+ * `license_plate` inside the parent vehicle. The named step is NOT
28234
+ * inferred — these FRAME-space boxes are its output — and its
28235
+ * requested children (the plate reader) run on them. Absent ⇒ every
28236
+ * requested step infers as before.
28237
+ */
28238
+ supplied: zod.z.object({
28239
+ stepId: zod.z.string(),
28240
+ modelId: zod.z.string(),
28241
+ boxes: zod.z.array(zod.z.object({
28242
+ bbox: NativeCropBboxSchema,
28243
+ score: zod.z.number()
28244
+ })).min(1)
28245
+ }).optional()
27900
28246
  }), zod.z.object({ details: zod.z.array(DetailResultSchema) }).nullable(), { kind: "mutation" }),
27901
28247
  /**
27902
28248
  * Run ONE enrichment step against caller-supplied pixels, with NO camera
@@ -37596,6 +37942,27 @@ var ViewerEndpointsSchema = zod.z.object({
37596
37942
  /** What the ranking currently resolves to (may be empty if nothing is up). */
37597
37943
  resolved: zod.z.array(zod.z.string()).readonly()
37598
37944
  });
37945
+ /**
37946
+ * One audience's hub address (see `hub-address.ts`): the operator's stored
37947
+ * override, the address in use, and where it came from.
37948
+ */
37949
+ var HubAddressSnapshotSchema = zod.z.object({
37950
+ /** The operator's override, or null for automatic. */
37951
+ override: zod.z.string().nullable(),
37952
+ /** The address in use, or null when nothing qualifies (never loopback). */
37953
+ resolved: zod.z.string().nullable(),
37954
+ source: zod.z.enum([
37955
+ "override",
37956
+ "auto",
37957
+ "none"
37958
+ ])
37959
+ });
37960
+ var HubAddressesSchema = zod.z.object({
37961
+ /** "Hub address for agents" — agents' bundle/model pulls, LAN devices. */
37962
+ cluster: HubAddressSnapshotSchema,
37963
+ /** "Public address for sign-in links" — e-mail links, OIDC, WebAuthn, OAuth2. */
37964
+ browser: HubAddressSnapshotSchema
37965
+ });
37599
37966
  var AllowedAddressesSchema = zod.z.object({
37600
37967
  /**
37601
37968
  * Allowlist of interface addresses operators have explicitly opted
@@ -37728,6 +38095,26 @@ var localNetworkCapability = {
37728
38095
  */
37729
38096
  setViewerEndpoints: require_sleep.method(zod.z.object({ baseUrls: zod.z.array(zod.z.string()).readonly() }), ViewerEndpointsSchema, { kind: "mutation" }),
37730
38097
  /**
38098
+ * The hub's address for each audience — agents (`cluster`) and sign-in
38099
+ * links (`browser`) — as every consumer must read it: the operator's
38100
+ * override when set, else the automatic pick from this cap's palette,
38101
+ * never loopback. The ONE answer to "at which address is this hub
38102
+ * reached?"; there is no environment variable for it.
38103
+ */
38104
+ getHubAddresses: require_sleep.method(zod.z.void(), HubAddressesSchema),
38105
+ /**
38106
+ * Set or clear (`baseUrl: null`) one audience's override. Validated: an
38107
+ * http(s) origin with a host, no credentials, no path, never loopback —
38108
+ * an invalid value is refused with the reason, nothing is stored.
38109
+ */
38110
+ setHubAddress: require_sleep.method(zod.z.object({
38111
+ audience: zod.z.enum(["cluster", "browser"]),
38112
+ baseUrl: zod.z.string().nullable()
38113
+ }), HubAddressesSchema, {
38114
+ kind: "mutation",
38115
+ auth: "admin"
38116
+ }),
38117
+ /**
37731
38118
  * Read the operator's allowlist. Empty = "auto" (no filter). Used
37732
38119
  * by the admin UI's address selector to seed its checkbox state.
37733
38120
  */
@@ -47869,7 +48256,9 @@ var FRIGATE_PLUS_TO_MACRO = {
47869
48256
  * - `attribute`: Frigate+ emits these INSIDE a parent box (a face inside a
47870
48257
  * person, a plate or a carrier logo on a vehicle). Mapping one to its
47871
48258
  * parent's macro would spawn a second, overlapping track for the same
47872
- * subject; CamStack derives faces and plates with its own detail steps.
48259
+ * subject. `face` and `license_plate` are instead declared as CROP supplies
48260
+ * (D730): the box becomes a detail child of the person / vehicle containing
48261
+ * it, when the face / plate step uses the root model.
47873
48262
  * - `no-macro`: an object with no detection macro to live under.
47874
48263
  */
47875
48264
  var FRIGATE_PLUS_UNMAPPED_LABELS = {
@@ -47915,17 +48304,18 @@ function buildFrigateClassMap(labels) {
47915
48304
  };
47916
48305
  }
47917
48306
  /**
47918
- * Everything a Frigate / Frigate+ entry derives from its labelmap: the classMap
47919
- * and the steps it fills (D715). Every Frigate builder spreads this, so the two
47920
- * cannot be derived from different label lists. A COCO labelmap gets its map
47921
- * and no fill.
48307
+ * Everything a Frigate / Frigate+ entry derives from ITS OWN labelmap: the
48308
+ * classMap and the steps it can supply (D730) — label and crop kinds alike.
48309
+ * Every Frigate builder spreads this at import, so the two cannot be derived
48310
+ * from different label lists, and no family is assumed to carry a label it
48311
+ * does not list.
47922
48312
  */
47923
48313
  function frigateLabelFields(labels) {
47924
48314
  const classMap = buildFrigateClassMap(labels);
47925
- const fills = deriveClassifierFills(labels, classMap);
47926
- return fills.length > 0 ? {
48315
+ const supplies = deriveRootSupplies(labels, classMap);
48316
+ return supplies.length > 0 ? {
47927
48317
  classMap,
47928
- fillsClassifierEffects: fills
48318
+ suppliesSteps: supplies
47929
48319
  } : { classMap };
47930
48320
  }
47931
48321
  //#endregion
@@ -53385,6 +53775,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
53385
53775
  addonId: null,
53386
53776
  access: "view"
53387
53777
  },
53778
+ "localNetwork.getHubAddresses": {
53779
+ capName: "local-network",
53780
+ capScope: "system",
53781
+ addonId: null,
53782
+ access: "view"
53783
+ },
53388
53784
  "localNetwork.getNotificationEndpoint": {
53389
53785
  capName: "local-network",
53390
53786
  capScope: "system",
@@ -53439,6 +53835,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
53439
53835
  addonId: null,
53440
53836
  access: "create"
53441
53837
  },
53838
+ "localNetwork.setHubAddress": {
53839
+ capName: "local-network",
53840
+ capScope: "system",
53841
+ addonId: null,
53842
+ access: "create"
53843
+ },
53442
53844
  "localNetwork.setNotificationEndpoint": {
53443
53845
  capName: "local-network",
53444
53846
  capScope: "system",
@@ -66001,6 +66403,8 @@ function createSystemProxy(api) {
66001
66403
  setNotificationEndpoint: (input) => dispatch("localNetwork", "setNotificationEndpoint", "mutation", input),
66002
66404
  getViewerEndpoints: (input) => dispatch("localNetwork", "getViewerEndpoints", "query", input),
66003
66405
  setViewerEndpoints: (input) => dispatch("localNetwork", "setViewerEndpoints", "mutation", input),
66406
+ getHubAddresses: (input) => dispatch("localNetwork", "getHubAddresses", "query", input),
66407
+ setHubAddress: (input) => dispatch("localNetwork", "setHubAddress", "mutation", input),
66004
66408
  getAllowedAddresses: (input) => dispatch("localNetwork", "getAllowedAddresses", "query", input),
66005
66409
  setAllowedAddresses: (input) => dispatch("localNetwork", "setAllowedAddresses", "mutation", input),
66006
66410
  resetAllowlistToBestMatch: (input) => dispatch("localNetwork", "resetAllowlistToBestMatch", "mutation", input),
@@ -68962,7 +69366,7 @@ var STATE_SUMMARY_VARS = [
68962
69366
  {
68963
69367
  name: "summarySection",
68964
69368
  label: "Summary: this section",
68965
- description: "The section a per-section summary row is about (D698); on a summary sent as one message, every section it reports, comma-separated.",
69369
+ description: "The section a per-section summary row is about; on a summary sent as one message, every section it reports, comma-separated.",
68966
69370
  example: "Batterie scariche",
68967
69371
  group: "system",
68968
69372
  families: ["rule"],
@@ -71044,6 +71448,33 @@ function isRemovedModelId(stepId, modelId) {
71044
71448
  return REMOVED_MODEL_IDS[stepId]?.includes(modelId) ?? false;
71045
71449
  }
71046
71450
  //#endregion
71451
+ //#region src/pipeline/root-face-crop.ts
71452
+ /** Side of the square, as a multiple of the face box's longer side. */
71453
+ var ROOT_FACE_REFINE_SCALE = 1.6;
71454
+ /**
71455
+ * The input the face detector sees the square at, in pixels. A face that
71456
+ * fills ~60% of a 160 px input is in the detector's measured sweet spot; the
71457
+ * same square fed at 640 puts a ~400 px face in front of a detector whose
71458
+ * largest anchors are far smaller.
71459
+ */
71460
+ var ROOT_FACE_REFINE_INPUT_PX = 160;
71461
+ /**
71462
+ * The square (frame-space pixels) a root face box is refined in: centred on
71463
+ * the box, side `ROOT_FACE_REFINE_SCALE ×` its longer side, slid inside the
71464
+ * frame, and shrunk only when the frame's shorter side is smaller. Pure.
71465
+ */
71466
+ function deriveRootFaceRefineRect(face, frameWidth, frameHeight) {
71467
+ const side = Math.min(Math.max(face.w, face.h) * ROOT_FACE_REFINE_SCALE, Math.min(frameWidth, frameHeight));
71468
+ const cx = face.x + face.w / 2;
71469
+ const cy = face.y + face.h / 2;
71470
+ return {
71471
+ x: Math.min(Math.max(0, cx - side / 2), frameWidth - side),
71472
+ y: Math.min(Math.max(0, cy - side / 2), frameHeight - side),
71473
+ w: side,
71474
+ h: side
71475
+ };
71476
+ }
71477
+ //#endregion
71047
71478
  //#region src/pipeline/detail-crop.ts
71048
71479
  /**
71049
71480
  * THE detail-crop convention — the single derivation of the rectangle a
@@ -73323,6 +73754,8 @@ exports.CONNECTION_TEST_TIMEOUT_MS = CONNECTION_TEST_TIMEOUT_MS;
73323
73754
  exports.CONTAINER_CHILD_PRIORITY = CONTAINER_CHILD_PRIORITY;
73324
73755
  exports.CORE_BLOCKS_ADDON_ID = CORE_BLOCKS_ADDON_ID;
73325
73756
  exports.CORE_BLOCK_ADDON_PREFIX = CORE_BLOCK_ADDON_PREFIX;
73757
+ exports.CROP_SUPPLY_SOURCES = CROP_SUPPLY_SOURCES;
73758
+ exports.CROP_SUPPLY_STEP_IDS = CROP_SUPPLY_STEP_IDS;
73326
73759
  exports.CUSTOMIZATION_BLOCK_NAME_PREFIX = require_composition.CUSTOMIZATION_BLOCK_NAME_PREFIX;
73327
73760
  exports.CalendarColorSchema = CalendarColorSchema;
73328
73761
  exports.CalendarEntrySchema = CalendarEntrySchema;
@@ -73515,7 +73948,6 @@ exports.DEFAULT_EVENTS_BAND_BUFFER_SEC = DEFAULT_EVENTS_BAND_BUFFER_SEC;
73515
73948
  exports.DEFAULT_EVENT_COLOR = DEFAULT_EVENT_COLOR;
73516
73949
  exports.DEFAULT_FEATURES = DEFAULT_FEATURES;
73517
73950
  exports.DEFAULT_FIRST_SIGHTING_FRESHNESS_MS = require_composition.DEFAULT_FIRST_SIGHTING_FRESHNESS_MS;
73518
- exports.DEFAULT_LABEL_LINK_POLICY = DEFAULT_LABEL_LINK_POLICY;
73519
73951
  exports.DEFAULT_MIN_LANDMARK_FACE_SIZE_PX = DEFAULT_MIN_LANDMARK_FACE_SIZE_PX;
73520
73952
  exports.DEFAULT_NATIVE_LEASE_SETTINGS = DEFAULT_NATIVE_LEASE_SETTINGS;
73521
73953
  exports.DEFAULT_OVERLAY_LAYERS = DEFAULT_OVERLAY_LAYERS;
@@ -73692,9 +74124,6 @@ exports.ExtensionSourceSchema = ExtensionSourceSchema;
73692
74124
  exports.FEEDER_EXAMPLE_ADDON_ID = FEEDER_EXAMPLE_ADDON_ID;
73693
74125
  exports.FEEDER_EXAMPLE_HA_DEVICE_ID = FEEDER_EXAMPLE_HA_DEVICE_ID;
73694
74126
  exports.FFMPEG_PATH_ENV = require_composition.FFMPEG_PATH_ENV;
73695
- exports.FILLABLE_STEP_IDS = FILLABLE_STEP_IDS;
73696
- exports.FILLABLE_STEP_MACRO = FILLABLE_STEP_MACRO;
73697
- exports.FILLABLE_STEP_VOCABULARIES = FILLABLE_STEP_VOCABULARIES;
73698
74127
  exports.FIRST_LEVEL_MACRO_CLASSES = FIRST_LEVEL_MACRO_CLASSES;
73699
74128
  exports.FRIGATE_PLUS_TO_MACRO = FRIGATE_PLUS_TO_MACRO;
73700
74129
  exports.FRIGATE_PLUS_UNMAPPED_LABELS = FRIGATE_PLUS_UNMAPPED_LABELS;
@@ -73708,7 +74137,6 @@ exports.FeatureManifestSchema = FeatureManifestSchema;
73708
74137
  exports.FeatureProbeStatusSchema = FeatureProbeStatusSchema;
73709
74138
  exports.FieldClaimModeSchema = FieldClaimModeSchema;
73710
74139
  exports.FieldClaimSchema = FieldClaimSchema;
73711
- exports.FillsClassifierEffectSchema = FillsClassifierEffectSchema;
73712
74140
  exports.FloodStatusSchema = FloodStatusSchema;
73713
74141
  exports.Fmp4BoxSplitter = require_composition.Fmp4BoxSplitter;
73714
74142
  exports.FrameHandleFormatSchema = require_sleep.FrameHandleFormatSchema;
@@ -73757,8 +74185,9 @@ exports.IntercomAbilitySchema = IntercomAbilitySchema;
73757
74185
  exports.IntercomStatusSchema = IntercomStatusSchema;
73758
74186
  exports.KNOWN_CAP_NAMES = KNOWN_CAP_NAMES;
73759
74187
  exports.KeyEventSchema = KeyEventSchema;
73760
- exports.LABEL_LINK_POLICIES = LABEL_LINK_POLICIES;
73761
- exports.LABEL_LINK_SETTING_KEY = LABEL_LINK_SETTING_KEY;
74188
+ exports.LABEL_SUPPLY_MACRO = LABEL_SUPPLY_MACRO;
74189
+ exports.LABEL_SUPPLY_STEP_IDS = LABEL_SUPPLY_STEP_IDS;
74190
+ exports.LABEL_SUPPLY_VOCABULARIES = LABEL_SUPPLY_VOCABULARIES;
73762
74191
  exports.LEGACY_READ_ONLY_CONFIG_KEY = LEGACY_READ_ONLY_CONFIG_KEY;
73763
74192
  exports.LINKED_DEVICES_SLOT = LINKED_DEVICES_SLOT;
73764
74193
  exports.LINKED_LABEL_STEP_PREFIX = LINKED_LABEL_STEP_PREFIX;
@@ -74282,6 +74711,10 @@ exports.ROOM_EXAMPLE_MOTION_SOURCES = ROOM_EXAMPLE_MOTION_SOURCES;
74282
74711
  exports.ROOM_EXAMPLE_TEMPERATURE_SOURCES = ROOM_EXAMPLE_TEMPERATURE_SOURCES;
74283
74712
  exports.ROOM_OCCUPANCY_WINDOW_MS = ROOM_OCCUPANCY_WINDOW_MS;
74284
74713
  exports.ROOT_BUCKET_KEY = ROOT_BUCKET_KEY;
74714
+ exports.ROOT_CHILD_CONTAINMENT_MIN = ROOT_CHILD_CONTAINMENT_MIN;
74715
+ exports.ROOT_FACE_REFINE_INPUT_PX = ROOT_FACE_REFINE_INPUT_PX;
74716
+ exports.ROOT_FACE_REFINE_SCALE = ROOT_FACE_REFINE_SCALE;
74717
+ exports.ROOT_SUPPLIABLE_STEP_IDS = ROOT_SUPPLIABLE_STEP_IDS;
74285
74718
  exports.RUNTIME_DEFAULTS = RUNTIME_DEFAULTS;
74286
74719
  exports.RUNTIME_STATE_POLICY = RUNTIME_STATE_POLICY;
74287
74720
  exports.RUNTIME_STATE_REFRESH_MISS_COOLDOWN_MS = RUNTIME_STATE_REFRESH_MISS_COOLDOWN_MS;
@@ -74366,6 +74799,7 @@ exports.RetrainStatusSchema = RetrainStatusSchema;
74366
74799
  exports.RetrainTrackSchema = RetrainTrackSchema;
74367
74800
  exports.RetrainTransitionResultSchema = RetrainTransitionResultSchema;
74368
74801
  exports.RingBuffer = RingBuffer;
74802
+ exports.RootStepSupplySchema = RootStepSupplySchema;
74369
74803
  exports.RtpSourceSchema = RtpSourceSchema;
74370
74804
  exports.RtspRestreamEntrySchema = RtspRestreamEntrySchema;
74371
74805
  exports.RunnerCameraConfigSchema = RunnerCameraConfigSchema;
@@ -74517,6 +74951,7 @@ exports.SubscribeAudioChunksInputSchema = require_sleep.SubscribeAudioChunksInpu
74517
74951
  exports.SubscribeAudioChunksResultSchema = require_sleep.SubscribeAudioChunksResultSchema;
74518
74952
  exports.SubscribeFramesInputSchema = require_sleep.SubscribeFramesInputSchema;
74519
74953
  exports.SubscribeFramesResultSchema = require_sleep.SubscribeFramesResultSchema;
74954
+ exports.SuppliedRootOutputSchema = SuppliedRootOutputSchema;
74520
74955
  exports.SwitchStatusSchema = SwitchStatusSchema;
74521
74956
  exports.SystemMetricsSchema = SystemMetricsSchema;
74522
74957
  exports.SystemMirror = SystemMirror;
@@ -74574,6 +75009,8 @@ exports.TransportPlaneSchema = TransportPlaneSchema;
74574
75009
  exports.TurnServerSchema = TurnServerSchema;
74575
75010
  exports.UNATTRIBUTED_BUCKET_KEY = UNATTRIBUTED_BUCKET_KEY;
74576
75011
  exports.UNIT_TABLE = UNIT_TABLE;
75012
+ exports.USE_ROOT_MODEL_DEFAULTS = USE_ROOT_MODEL_DEFAULTS;
75013
+ exports.USE_ROOT_MODEL_SETTING_KEY = USE_ROOT_MODEL_SETTING_KEY;
74577
75014
  exports.UnifiedBrokerInfoSchema = BrokerInfoSchema;
74578
75015
  exports.UnitConversionError = UnitConversionError;
74579
75016
  exports.UnstampedEventMediaCountSchema = UnstampedEventMediaCountSchema;
@@ -74668,6 +75105,7 @@ exports.alarmPatchLanded = alarmPatchLanded;
74668
75105
  exports.alarmProfileById = alarmProfileById;
74669
75106
  exports.alertsCapability = alertsCapability;
74670
75107
  exports.allDoActions = allDoActions;
75108
+ exports.allowedSuppliedEffect = allowedSuppliedEffect;
74671
75109
  exports.ambientLightSensorCapability = ambientLightSensorCapability;
74672
75110
  exports.applyBlockingEdit = applyBlockingEdit;
74673
75111
  exports.applyModeDelaysEdits = applyModeDelaysEdits;
@@ -74774,6 +75212,7 @@ exports.connectivityCapability = connectivityCapability;
74774
75212
  exports.consumableLowPercentOf = consumableLowPercentOf;
74775
75213
  exports.consumablesCapability = consumablesCapability;
74776
75214
  exports.contactCapability = contactCapability;
75215
+ exports.containingParentIndex = containingParentIndex;
74777
75216
  exports.controlCapability = controlCapability;
74778
75217
  exports.convertPresetFeature = convertPresetFeature;
74779
75218
  exports.convertUnit = convertUnit;
@@ -74817,15 +75256,18 @@ exports.defineExtensionSlotProvider = defineExtensionSlotProvider;
74817
75256
  exports.deleteAlarmProfile = deleteAlarmProfile;
74818
75257
  exports.deriveBatteryPresence = deriveBatteryPresence;
74819
75258
  exports.deriveCameraSwitches = deriveCameraSwitches;
74820
- exports.deriveClassifierFills = deriveClassifierFills;
74821
75259
  exports.deriveDetailCropRect = deriveDetailCropRect;
74822
75260
  exports.derivePostTriggeredAction = derivePostTriggeredAction;
74823
75261
  exports.deriveRecordingMode = deriveRecordingMode;
75262
+ exports.deriveRootFaceRefineRect = deriveRootFaceRefineRect;
75263
+ exports.deriveRootSupplies = deriveRootSupplies;
74824
75264
  exports.describeComposableCaps = describeComposableCaps;
74825
75265
  exports.describeCustomActions = require_sleep.describeCustomActions;
74826
75266
  exports.describeModelVariant = describeModelVariant;
74827
75267
  exports.describeOnboardClamp = describeOnboardClamp;
74828
75268
  exports.describeOnboardRefusal = describeOnboardRefusal;
75269
+ exports.describeRootSupplies = describeRootSupplies;
75270
+ exports.describeRootSupply = describeRootSupply;
74829
75271
  exports.describeStateField = describeStateField;
74830
75272
  exports.describeSystemEventDeliveryProblem = describeSystemEventDeliveryProblem;
74831
75273
  exports.describeSystemEventFamilyProblem = describeSystemEventFamilyProblem;
@@ -74909,7 +75351,6 @@ exports.feederExampleSources = feederExampleSources;
74909
75351
  exports.ffmpegRate = ffmpegRate;
74910
75352
  exports.fieldReads = require_composition.fieldReads;
74911
75353
  exports.filesystemBrowseCapability = filesystemBrowseCapability;
74912
- exports.fillFor = fillFor;
74913
75354
  exports.findCandidateCycles = findCandidateCycles;
74914
75355
  exports.findCompositionCycles = findCompositionCycles;
74915
75356
  exports.findTimezone = findTimezone;
@@ -74934,6 +75375,7 @@ exports.gifFromMp4Args = gifFromMp4Args;
74934
75375
  exports.hasMotionTrigger = hasMotionTrigger;
74935
75376
  exports.hfModelUrl = hfModelUrl;
74936
75377
  exports.htmlToText = htmlToText;
75378
+ exports.hubAddressHostname = hubAddressHostname;
74937
75379
  exports.hubMotionNativeProvider = hubMotionNativeProvider;
74938
75380
  exports.humidifierCapability = humidifierCapability;
74939
75381
  exports.humiditySensorCapability = humiditySensorCapability;
@@ -74960,7 +75402,6 @@ exports.isAudioRule = isAudioRule;
74960
75402
  exports.isBaseConditionKey = isBaseConditionKey;
74961
75403
  exports.isBatteryPresenceFault = isBatteryPresenceFault;
74962
75404
  exports.isClusterScopedStep = isClusterScopedStep;
74963
- exports.isCocoLabelmap = isCocoLabelmap;
74964
75405
  exports.isCollectionArrayMethod = isCollectionArrayMethod;
74965
75406
  exports.isDefaultAlarmProfileId = isDefaultAlarmProfileId;
74966
75407
  exports.isDeployableToAgent = isDeployableToAgent;
@@ -74974,11 +75415,11 @@ exports.isEmbeddingModelFailed = isEmbeddingModelFailed;
74974
75415
  exports.isEvent = require_sleep.isEvent;
74975
75416
  exports.isEventKindLabelKey = isEventKindLabelKey;
74976
75417
  exports.isEventOwnerType = isEventOwnerType;
74977
- exports.isFillableStepId = isFillableStepId;
74978
75418
  exports.isFirstLevelMacroClass = isFirstLevelMacroClass;
74979
75419
  exports.isHeldBackTemplateVar = isHeldBackTemplateVar;
74980
75420
  exports.isIsolatedBuiltin = isIsolatedBuiltin;
74981
75421
  exports.isKnownTemplateVar = isKnownTemplateVar;
75422
+ exports.isLabelSupplyStepId = isLabelSupplyStepId;
74982
75423
  exports.isLocationEnabled = isLocationEnabled;
74983
75424
  exports.isMediaOwnerType = isMediaOwnerType;
74984
75425
  exports.isNode = isNode;
@@ -74988,6 +75429,7 @@ exports.isOwnerOnlyEventCategory = require_event_category.isOwnerOnlyEventCatego
74988
75429
  exports.isRemovedModelId = isRemovedModelId;
74989
75430
  exports.isRestoredCap = isRestoredCap;
74990
75431
  exports.isRetiredClearKey = isRetiredClearKey;
75432
+ exports.isRootSuppliableStepId = isRootSuppliableStepId;
74991
75433
  exports.isSameAddonId = isSameAddonId;
74992
75434
  exports.isScheduleActive = isScheduleActive;
74993
75435
  exports.isSecretConfigField = isSecretConfigField;
@@ -75107,6 +75549,8 @@ exports.pickAppLinkHub = pickAppLinkHub;
75107
75549
  exports.pickClusterStepModels = pickClusterStepModels;
75108
75550
  exports.pickClusterStepSettings = pickClusterStepSettings;
75109
75551
  exports.pickDetailCropConvention = pickDetailCropConvention;
75552
+ exports.pickHubBaseUrl = pickHubBaseUrl;
75553
+ exports.pickHubHostname = pickHubHostname;
75110
75554
  exports.pickInvalidClusterStepModels = pickInvalidClusterStepModels;
75111
75555
  exports.pickNativeLeaseOverride = pickNativeLeaseOverride;
75112
75556
  exports.pickPreferredRtspEntry = pickPreferredRtspEntry;
@@ -75143,11 +75587,11 @@ exports.readDetailCropConvention = readDetailCropConvention;
75143
75587
  exports.readDeviceStateFrom = readDeviceStateFrom;
75144
75588
  exports.readHubMotionDetected = readHubMotionDetected;
75145
75589
  exports.readHubMotionStatus = readHubMotionStatus;
75146
- exports.readLabelLinkPolicy = readLabelLinkPolicy;
75147
75590
  exports.readMotionTriggeredBy = readMotionTriggeredBy;
75148
75591
  exports.readNativeLeaseOverride = readNativeLeaseOverride;
75149
75592
  exports.readNodePin = require_sleep.readNodePin;
75150
75593
  exports.readTimelapseGeneratedAt = readTimelapseGeneratedAt;
75594
+ exports.readUseRootModel = readUseRootModel;
75151
75595
  exports.readinessKey = require_sleep.readinessKey;
75152
75596
  exports.rebootCapability = rebootCapability;
75153
75597
  exports.reconcileBlockDevices = reconcileBlockDevices;
@@ -75180,8 +75624,8 @@ exports.resolveDeviceProfile = resolveDeviceProfile;
75180
75624
  exports.resolveEgressDecodeHwAccel = resolveEgressDecodeHwAccel;
75181
75625
  exports.resolveExportProfiles = resolveExportProfiles;
75182
75626
  exports.resolveFormat = resolveFormat;
75627
+ exports.resolveHubAddress = resolveHubAddress;
75183
75628
  exports.resolveHydratedFieldValue = require_sleep.resolveHydratedFieldValue;
75184
- exports.resolveLabelLink = resolveLabelLink;
75185
75629
  exports.resolveLocationIcon = resolveLocationIcon;
75186
75630
  exports.resolveLocationMode = resolveLocationMode;
75187
75631
  exports.resolveMethodAuth = resolveMethodAuth;
@@ -75190,12 +75634,15 @@ exports.resolveModeNotifyPolicy = resolveModeNotifyPolicy;
75190
75634
  exports.resolveMutate = resolveMutate;
75191
75635
  exports.resolvePoolMemoryPolicy = resolvePoolMemoryPolicy;
75192
75636
  exports.resolveRecordingProfiles = resolveRecordingProfiles;
75637
+ exports.resolveRootSupply = resolveRootSupply;
75193
75638
  exports.resolveRunnerId = resolveRunnerId;
75194
75639
  exports.resolveStreamMaps = require_composition.resolveStreamMaps;
75195
75640
  exports.resolveVariantModelId = resolveVariantModelId;
75196
75641
  exports.resolveViewableDeviceIds = resolveViewableDeviceIds;
75197
75642
  exports.roleSpec = roleSpec;
75198
75643
  exports.roomCompositionExample = roomCompositionExample;
75644
+ exports.rootSuppliesOf = rootSuppliesOf;
75645
+ exports.rootSupplyServes = rootSupplyServes;
75199
75646
  exports.ruleAutoTriggersAlarm = ruleAutoTriggersAlarm;
75200
75647
  exports.ruleBelongsToAlarm = ruleBelongsToAlarm;
75201
75648
  exports.ruleDeviceCompatCapNames = ruleDeviceCompatCapNames;
@@ -75265,6 +75712,7 @@ exports.strippedOfLegacyReadOnly = strippedOfLegacyReadOnly;
75265
75712
  exports.subKindsOf = subKindsOf;
75266
75713
  exports.summarisePrivacyAudio = summarisePrivacyAudio;
75267
75714
  exports.summarizeEffectiveScope = summarizeEffectiveScope;
75715
+ exports.supplyFor = supplyFor;
75268
75716
  exports.supportedRuntimes = supportedRuntimes;
75269
75717
  exports.switchCapability = switchCapability;
75270
75718
  exports.switchedOffIds = switchedOffIds;
@@ -75316,6 +75764,7 @@ exports.userPasskeysCapability = userPasskeysCapability;
75316
75764
  exports.vacuumControlCapability = vacuumControlCapability;
75317
75765
  exports.validateComposition = validateComposition;
75318
75766
  exports.validateExpressionSource = require_composition.validateExpressionSource;
75767
+ exports.validateHubAddressOverride = validateHubAddressOverride;
75319
75768
  exports.validateRecipeBounds = validateRecipeBounds;
75320
75769
  exports.valveCapability = valveCapability;
75321
75770
  exports.vectorDimFromBase64 = vectorDimFromBase64;