@camstack/addon-model-studio 1.1.201 → 1.1.203

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 (19) hide show
  1. package/THIRD_PARTY_MODELS.md +35 -27
  2. package/dist/{MotionZonesSettings-C5XCa2RN.mjs → MotionZonesSettings-Bf3wXZlv.mjs} +2 -2
  3. package/dist/{PrivacyMaskSettings-Byby1Qnl.mjs → PrivacyMaskSettings-CxaNRx4y.mjs} +4 -4
  4. package/dist/{SceneMonitorEditor-BehD1iD6.mjs → SceneMonitorEditor-6Njva8QD.mjs} +3 -3
  5. package/dist/_stub.js +3929 -3905
  6. package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_model_studio_page-BYPEJjop.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_model_studio_page-BY8XezL8.mjs} +4 -4
  7. package/dist/_virtual_mf___mfe_internal__addon_model_studio_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-De0PN1jX.mjs +26 -0
  8. package/dist/{hostInit-Ds4oKb79.mjs → hostInit-wXzg-Tk8.mjs} +3 -3
  9. package/dist/model-studio.addon.js +596 -47
  10. package/dist/model-studio.addon.mjs +596 -47
  11. package/dist/{player-overlays-BdsADMdm.mjs → player-overlays-DXZiCaYb.mjs} +1 -1
  12. package/dist/remoteEntry.js +1 -1
  13. package/dist/{responsive-orJ4AkQR.mjs → responsive-CTK4xC09.mjs} +1 -1
  14. package/dist/{scene-monitor-copy-CRMa4vtd.mjs → scene-monitor-copy-FMv2Ek7A.mjs} +1 -1
  15. package/dist/{square-CgcW-Db-.mjs → square-CB2wuPUO.mjs} +1 -1
  16. package/dist/{trash-2-Di341FuZ.mjs → trash-2-JwXG4MxN.mjs} +1 -1
  17. package/dist/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_model_studio_page__remoteEntry_js-CHD2bVBg.mjs → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_model_studio_page__remoteEntry_js-C0ebXZ4C.mjs} +1 -1
  18. package/package.json +1 -1
  19. package/dist/_virtual_mf___mfe_internal__addon_model_studio_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CX_tb6VB.mjs +0 -26
@@ -10926,6 +10926,478 @@ var ClipSearchStrictnessSchema = _enum([
10926
10926
  "balanced",
10927
10927
  "strict"
10928
10928
  ]);
10929
+ var COCO_80_LABELS = [
10930
+ {
10931
+ id: "person",
10932
+ name: "Person"
10933
+ },
10934
+ {
10935
+ id: "bicycle",
10936
+ name: "Bicycle"
10937
+ },
10938
+ {
10939
+ id: "car",
10940
+ name: "Car"
10941
+ },
10942
+ {
10943
+ id: "motorcycle",
10944
+ name: "Motorcycle"
10945
+ },
10946
+ {
10947
+ id: "airplane",
10948
+ name: "Airplane"
10949
+ },
10950
+ {
10951
+ id: "bus",
10952
+ name: "Bus"
10953
+ },
10954
+ {
10955
+ id: "train",
10956
+ name: "Train"
10957
+ },
10958
+ {
10959
+ id: "truck",
10960
+ name: "Truck"
10961
+ },
10962
+ {
10963
+ id: "boat",
10964
+ name: "Boat"
10965
+ },
10966
+ {
10967
+ id: "traffic light",
10968
+ name: "Traffic Light"
10969
+ },
10970
+ {
10971
+ id: "fire hydrant",
10972
+ name: "Fire Hydrant"
10973
+ },
10974
+ {
10975
+ id: "stop sign",
10976
+ name: "Stop Sign"
10977
+ },
10978
+ {
10979
+ id: "parking meter",
10980
+ name: "Parking Meter"
10981
+ },
10982
+ {
10983
+ id: "bench",
10984
+ name: "Bench"
10985
+ },
10986
+ {
10987
+ id: "bird",
10988
+ name: "Bird"
10989
+ },
10990
+ {
10991
+ id: "cat",
10992
+ name: "Cat"
10993
+ },
10994
+ {
10995
+ id: "dog",
10996
+ name: "Dog"
10997
+ },
10998
+ {
10999
+ id: "horse",
11000
+ name: "Horse"
11001
+ },
11002
+ {
11003
+ id: "sheep",
11004
+ name: "Sheep"
11005
+ },
11006
+ {
11007
+ id: "cow",
11008
+ name: "Cow"
11009
+ },
11010
+ {
11011
+ id: "elephant",
11012
+ name: "Elephant"
11013
+ },
11014
+ {
11015
+ id: "bear",
11016
+ name: "Bear"
11017
+ },
11018
+ {
11019
+ id: "zebra",
11020
+ name: "Zebra"
11021
+ },
11022
+ {
11023
+ id: "giraffe",
11024
+ name: "Giraffe"
11025
+ },
11026
+ {
11027
+ id: "backpack",
11028
+ name: "Backpack"
11029
+ },
11030
+ {
11031
+ id: "umbrella",
11032
+ name: "Umbrella"
11033
+ },
11034
+ {
11035
+ id: "handbag",
11036
+ name: "Handbag"
11037
+ },
11038
+ {
11039
+ id: "tie",
11040
+ name: "Tie"
11041
+ },
11042
+ {
11043
+ id: "suitcase",
11044
+ name: "Suitcase"
11045
+ },
11046
+ {
11047
+ id: "frisbee",
11048
+ name: "Frisbee"
11049
+ },
11050
+ {
11051
+ id: "skis",
11052
+ name: "Skis"
11053
+ },
11054
+ {
11055
+ id: "snowboard",
11056
+ name: "Snowboard"
11057
+ },
11058
+ {
11059
+ id: "sports ball",
11060
+ name: "Sports Ball"
11061
+ },
11062
+ {
11063
+ id: "kite",
11064
+ name: "Kite"
11065
+ },
11066
+ {
11067
+ id: "baseball bat",
11068
+ name: "Baseball Bat"
11069
+ },
11070
+ {
11071
+ id: "baseball glove",
11072
+ name: "Baseball Glove"
11073
+ },
11074
+ {
11075
+ id: "skateboard",
11076
+ name: "Skateboard"
11077
+ },
11078
+ {
11079
+ id: "surfboard",
11080
+ name: "Surfboard"
11081
+ },
11082
+ {
11083
+ id: "tennis racket",
11084
+ name: "Tennis Racket"
11085
+ },
11086
+ {
11087
+ id: "bottle",
11088
+ name: "Bottle"
11089
+ },
11090
+ {
11091
+ id: "wine glass",
11092
+ name: "Wine Glass"
11093
+ },
11094
+ {
11095
+ id: "cup",
11096
+ name: "Cup"
11097
+ },
11098
+ {
11099
+ id: "fork",
11100
+ name: "Fork"
11101
+ },
11102
+ {
11103
+ id: "knife",
11104
+ name: "Knife"
11105
+ },
11106
+ {
11107
+ id: "spoon",
11108
+ name: "Spoon"
11109
+ },
11110
+ {
11111
+ id: "bowl",
11112
+ name: "Bowl"
11113
+ },
11114
+ {
11115
+ id: "banana",
11116
+ name: "Banana"
11117
+ },
11118
+ {
11119
+ id: "apple",
11120
+ name: "Apple"
11121
+ },
11122
+ {
11123
+ id: "sandwich",
11124
+ name: "Sandwich"
11125
+ },
11126
+ {
11127
+ id: "orange",
11128
+ name: "Orange"
11129
+ },
11130
+ {
11131
+ id: "broccoli",
11132
+ name: "Broccoli"
11133
+ },
11134
+ {
11135
+ id: "carrot",
11136
+ name: "Carrot"
11137
+ },
11138
+ {
11139
+ id: "hot dog",
11140
+ name: "Hot Dog"
11141
+ },
11142
+ {
11143
+ id: "pizza",
11144
+ name: "Pizza"
11145
+ },
11146
+ {
11147
+ id: "donut",
11148
+ name: "Donut"
11149
+ },
11150
+ {
11151
+ id: "cake",
11152
+ name: "Cake"
11153
+ },
11154
+ {
11155
+ id: "chair",
11156
+ name: "Chair"
11157
+ },
11158
+ {
11159
+ id: "couch",
11160
+ name: "Couch"
11161
+ },
11162
+ {
11163
+ id: "potted plant",
11164
+ name: "Potted Plant"
11165
+ },
11166
+ {
11167
+ id: "bed",
11168
+ name: "Bed"
11169
+ },
11170
+ {
11171
+ id: "dining table",
11172
+ name: "Dining Table"
11173
+ },
11174
+ {
11175
+ id: "toilet",
11176
+ name: "Toilet"
11177
+ },
11178
+ {
11179
+ id: "tv",
11180
+ name: "TV"
11181
+ },
11182
+ {
11183
+ id: "laptop",
11184
+ name: "Laptop"
11185
+ },
11186
+ {
11187
+ id: "mouse",
11188
+ name: "Mouse"
11189
+ },
11190
+ {
11191
+ id: "remote",
11192
+ name: "Remote"
11193
+ },
11194
+ {
11195
+ id: "keyboard",
11196
+ name: "Keyboard"
11197
+ },
11198
+ {
11199
+ id: "cell phone",
11200
+ name: "Cell Phone"
11201
+ },
11202
+ {
11203
+ id: "microwave",
11204
+ name: "Microwave"
11205
+ },
11206
+ {
11207
+ id: "oven",
11208
+ name: "Oven"
11209
+ },
11210
+ {
11211
+ id: "toaster",
11212
+ name: "Toaster"
11213
+ },
11214
+ {
11215
+ id: "sink",
11216
+ name: "Sink"
11217
+ },
11218
+ {
11219
+ id: "refrigerator",
11220
+ name: "Refrigerator"
11221
+ },
11222
+ {
11223
+ id: "book",
11224
+ name: "Book"
11225
+ },
11226
+ {
11227
+ id: "clock",
11228
+ name: "Clock"
11229
+ },
11230
+ {
11231
+ id: "vase",
11232
+ name: "Vase"
11233
+ },
11234
+ {
11235
+ id: "scissors",
11236
+ name: "Scissors"
11237
+ },
11238
+ {
11239
+ id: "teddy bear",
11240
+ name: "Teddy Bear"
11241
+ },
11242
+ {
11243
+ id: "hair drier",
11244
+ name: "Hair Drier"
11245
+ },
11246
+ {
11247
+ id: "toothbrush",
11248
+ name: "Toothbrush"
11249
+ }
11250
+ ];
11251
+ new Set([
11252
+ {
11253
+ id: "person",
11254
+ name: "Person"
11255
+ },
11256
+ {
11257
+ id: "vehicle",
11258
+ name: "Vehicle"
11259
+ },
11260
+ {
11261
+ id: "animal",
11262
+ name: "Animal"
11263
+ },
11264
+ {
11265
+ id: "package",
11266
+ name: "Package"
11267
+ }
11268
+ ].map((l) => l.id));
11269
+ var COCO_TO_MACRO = {
11270
+ mapping: {
11271
+ person: "person",
11272
+ bicycle: "vehicle",
11273
+ car: "vehicle",
11274
+ motorcycle: "vehicle",
11275
+ airplane: "vehicle",
11276
+ bus: "vehicle",
11277
+ train: "vehicle",
11278
+ truck: "vehicle",
11279
+ boat: "vehicle",
11280
+ bird: "animal",
11281
+ cat: "animal",
11282
+ dog: "animal",
11283
+ horse: "animal",
11284
+ sheep: "animal",
11285
+ cow: "animal",
11286
+ elephant: "animal",
11287
+ bear: "animal",
11288
+ zebra: "animal",
11289
+ giraffe: "animal",
11290
+ suitcase: "package",
11291
+ backpack: "package",
11292
+ handbag: "package"
11293
+ },
11294
+ preserveOriginal: false
11295
+ };
11296
+ /** Steps a root detector may declare it fills. */
11297
+ var FILLABLE_STEP_IDS = [
11298
+ "animal-classifier",
11299
+ "vehicle-classifier",
11300
+ "package-detection"
11301
+ ];
11302
+ /**
11303
+ * The EFFECT vocabulary of each fillable step: exactly the strings the step
11304
+ * itself emits, in its own spelling. A linked label is one of these and nothing
11305
+ * else, so a tier-1 value means the same thing whichever writer produced it.
11306
+ *
11307
+ * - `animal-classifier`: the PRIMARY model's `-labels.json` (Open Images V7,
11308
+ * 8 classes) — also the species allow-list the step offers.
11309
+ * - `vehicle-classifier`: `vehicle-type-v1-labels.json`, capitalised as the
11310
+ * model emits them (the classifier writes `winner.class` verbatim).
11311
+ * - `package-detection`: its one output class.
11312
+ *
11313
+ * `scripts/check-label-link-vocabulary.ts` fails the build if a model entry's
11314
+ * `labelToEffect` names anything outside this table.
11315
+ */
11316
+ var FILLABLE_STEP_VOCABULARIES = {
11317
+ "animal-classifier": [
11318
+ "bird",
11319
+ "cat",
11320
+ "cow",
11321
+ "deer",
11322
+ "dog",
11323
+ "horse",
11324
+ "sheep",
11325
+ "squirrel"
11326
+ ],
11327
+ "vehicle-classifier": [
11328
+ "Ambulance",
11329
+ "Bicycle",
11330
+ "Bus",
11331
+ "Car",
11332
+ "Motorcycle",
11333
+ "Taxi",
11334
+ "Truck",
11335
+ "Van"
11336
+ ],
11337
+ "package-detection": ["package"]
11338
+ };
11339
+ /** The macro a detection must carry for the step to apply to it. */
11340
+ var FILLABLE_STEP_MACRO = {
11341
+ "animal-classifier": "animal",
11342
+ "vehicle-classifier": "vehicle",
11343
+ "package-detection": "package"
11344
+ };
11345
+ /**
11346
+ * Raw detector labels that name a vocabulary entry under another spelling.
11347
+ * Case-insensitive equality covers the rest (`car` → `Car`).
11348
+ */
11349
+ var EFFECT_ALIASES = {
11350
+ "animal-classifier": {},
11351
+ "vehicle-classifier": {
11352
+ school_bus: "Bus",
11353
+ garbage_truck: "Truck"
11354
+ },
11355
+ "package-detection": {}
11356
+ };
11357
+ /**
11358
+ * A labelmap is COCO when it carries at least half of the COCO-80 classes. A
11359
+ * COCO detector NEVER fills a step (operator decision, D715): its `dog` / `car`
11360
+ * is the generic class the classifier exists to refine, and its six animal
11361
+ * classes would otherwise read as "fills animal-classifier 6/8". Frigate+
11362
+ * shares about a dozen COCO names; a COCO-80 or COCO-91 labelmap carries ~80.
11363
+ */
11364
+ function isCocoLabelmap(labels) {
11365
+ const present = new Set(labels);
11366
+ return COCO_80_LABELS.filter((l) => present.has(l.id)).length * 2 >= COCO_80_LABELS.length;
11367
+ }
11368
+ function effectFor(stepId, label) {
11369
+ const alias = EFFECT_ALIASES[stepId][label];
11370
+ if (alias !== void 0) return alias;
11371
+ const folded = label.toLowerCase();
11372
+ return FILLABLE_STEP_VOCABULARIES[stepId].find((v) => v.toLowerCase() === folded);
11373
+ }
11374
+ /**
11375
+ * Which steps a root detector fills, from its labelmap and classMap. A label
11376
+ * counts for a step only when the model's classMap sends it to that step's
11377
+ * macro AND it names a vocabulary entry. A step none of the labels reach is
11378
+ * not declared; a COCO labelmap declares nothing.
11379
+ */
11380
+ function deriveClassifierFills(labels, classMap) {
11381
+ if (classMap === void 0 || isCocoLabelmap(labels)) return [];
11382
+ const fills = [];
11383
+ for (const stepId of FILLABLE_STEP_IDS) {
11384
+ const labelToEffect = {};
11385
+ for (const label of labels) {
11386
+ if (classMap.mapping[label] !== FILLABLE_STEP_MACRO[stepId]) continue;
11387
+ const effect = effectFor(stepId, label);
11388
+ if (effect !== void 0) labelToEffect[label] = effect;
11389
+ }
11390
+ const covered = new Set(Object.values(labelToEffect));
11391
+ if (covered.size === 0) continue;
11392
+ const uncovered = FILLABLE_STEP_VOCABULARIES[stepId].filter((v) => !covered.has(v));
11393
+ fills.push({
11394
+ stepId,
11395
+ labelToEffect,
11396
+ uncovered
11397
+ });
11398
+ }
11399
+ return fills;
11400
+ }
10929
11401
  var MODEL_FORMATS = [
10930
11402
  "onnx",
10931
11403
  "coreml",
@@ -11058,6 +11530,12 @@ var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { wei
11058
11530
  /** True when the weights or their data forbid commercial use. */
11059
11531
  nonCommercial: boolean().optional()
11060
11532
  }));
11533
+ /** One `fillsClassifierEffects` entry — see `ModelCatalogEntry.fillsClassifierEffects`. */
11534
+ var FillsClassifierEffectSchema = object({
11535
+ stepId: _enum(FILLABLE_STEP_IDS),
11536
+ labelToEffect: record(string(), string()),
11537
+ uncovered: array(string()).readonly()
11538
+ });
11061
11539
  var ModelCatalogEntrySchema = object({
11062
11540
  id: string(),
11063
11541
  name: string(),
@@ -11184,6 +11662,16 @@ var ModelCatalogEntrySchema = object({
11184
11662
  */
11185
11663
  classMap: DetectionCatalogClassMapSchema.optional(),
11186
11664
  /**
11665
+ * The pipeline steps this ROOT detector already does the work of (D715):
11666
+ * its labels name the effect the step exists to produce (`deer` for
11667
+ * `animal-classifier`, `package` for `package-detection`). Derived from the
11668
+ * labelmap by `deriveClassifierFills`, never hand-written; a COCO model
11669
+ * declares none. Whether a declaration is honoured is the step's own
11670
+ * `labelLink` policy (`resolveLabelLink`). `labelToEffect` values are in
11671
+ * `FILLABLE_STEP_VOCABULARIES` (guard `check-label-link-vocabulary`).
11672
+ */
11673
+ fillsClassifierEffects: array(FillsClassifierEffectSchema).readonly().optional(),
11674
+ /**
11187
11675
  * The model's CLIP feature-space contract (text encoder, dimension, vector
11188
11676
  * index, token window, search floor) — see `clip-model.ts`. Present ONLY on a
11189
11677
  * CLIP image encoder; its absence is what "not a CLIP model" means to the
@@ -18144,51 +18632,6 @@ method(object({}), array(TargetKindSchema)), method(object({}), array(TargetSche
18144
18632
  kind: "mutation",
18145
18633
  auth: "admin"
18146
18634
  });
18147
- new Set([
18148
- {
18149
- id: "person",
18150
- name: "Person"
18151
- },
18152
- {
18153
- id: "vehicle",
18154
- name: "Vehicle"
18155
- },
18156
- {
18157
- id: "animal",
18158
- name: "Animal"
18159
- },
18160
- {
18161
- id: "package",
18162
- name: "Package"
18163
- }
18164
- ].map((l) => l.id));
18165
- var COCO_TO_MACRO = {
18166
- mapping: {
18167
- person: "person",
18168
- bicycle: "vehicle",
18169
- car: "vehicle",
18170
- motorcycle: "vehicle",
18171
- airplane: "vehicle",
18172
- bus: "vehicle",
18173
- train: "vehicle",
18174
- truck: "vehicle",
18175
- boat: "vehicle",
18176
- bird: "animal",
18177
- cat: "animal",
18178
- dog: "animal",
18179
- horse: "animal",
18180
- sheep: "animal",
18181
- cow: "animal",
18182
- elephant: "animal",
18183
- bear: "animal",
18184
- zebra: "animal",
18185
- giraffe: "animal",
18186
- suitcase: "package",
18187
- backpack: "package",
18188
- handbag: "package"
18189
- },
18190
- preserveOriginal: false
18191
- };
18192
18635
  var AUDIO_MACRO_LABELS = [
18193
18636
  {
18194
18637
  id: "speech",
@@ -18946,6 +19389,8 @@ var NcSystemEventKindSchema = _enum([
18946
19389
  "stream-offline",
18947
19390
  "node-online",
18948
19391
  "node-offline",
19392
+ "node-restarting",
19393
+ "node-updating",
18949
19394
  "node-inference-unavailable",
18950
19395
  "detection-blind",
18951
19396
  "addon-crash-loop",
@@ -23592,7 +24037,8 @@ var PipelineModelOptionSchema = object({
23592
24037
  group: ModelVariantGroupSchema.optional(),
23593
24038
  legacy: boolean().optional(),
23594
24039
  provider: ModelProviderIdSchema.optional(),
23595
- defaultConfidence: number().optional()
24040
+ defaultConfidence: number().optional(),
24041
+ fillsClassifierEffects: array(FillsClassifierEffectSchema).readonly().optional()
23596
24042
  });
23597
24043
  var ConfigFieldBridge = custom();
23598
24044
  var PipelineAddonSchemaSchema = object({
@@ -31476,7 +31922,8 @@ object({
31476
31922
  * writes this slice (not even a boot seed), and neither does the runner's
31477
31923
  * phase machine: its phase is "a session is attached" for every on-motion
31478
31924
  * session, not motion, and it now has its own `DetectionPhaseTransition`.
31479
- * A provider's `isDetected` answers from the hub's slice.
31925
+ * A provider's `isDetected` and `getStatus` answer from the hub's slice
31926
+ * (`hubMotionNativeProvider`).
31480
31927
  * - **Sensors** (Home Assistant binary sensors, Homematic, Matter, Alexa
31481
31928
  * imports) — the provider pushes both edges itself, from the upstream
31482
31929
  * system's own state change. That is the sensor's own fact.
@@ -36607,6 +37054,82 @@ DeviceType.Camera, method(object({
36607
37054
  package: array(ZoneRuleSchema).readonly()
36608
37055
  });
36609
37056
  SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
37057
+ function isClassMapMacroTarget(value) {
37058
+ return CLASS_MAP_MACRO_TARGETS.some((target) => target === value);
37059
+ }
37060
+ /**
37061
+ * Raw Frigate+ label → detection macro. Every label of the documented
37062
+ * Frigate+ base set (docs.frigate.video/plus, verified 2026-08-21) is either
37063
+ * here or in {@link FRIGATE_PLUS_UNMAPPED_LABELS}, with the reason it is not.
37064
+ *
37065
+ * Why this exists: a Frigate+ import used to carry NO classMap, so it inherited
37066
+ * the step's `COCO_TO_MACRO` (`preserveOriginal: false`) and the executor
37067
+ * dropped every label COCO does not name — deer, raccoon, fox, squirrel, goat,
37068
+ * rabbit, skunk, kangaroo, possum, rodent, school_bus, garbage_truck and even
37069
+ * `package` vanished as `class-filter` discards. The executor keeps the raw
37070
+ * label as `originalClass` whenever the map resolves it, so the fine identity
37071
+ * survives under the macro.
37072
+ */
37073
+ var FRIGATE_PLUS_TO_MACRO = {
37074
+ person: "person",
37075
+ baby: "person",
37076
+ car: "vehicle",
37077
+ motorcycle: "vehicle",
37078
+ bicycle: "vehicle",
37079
+ boat: "vehicle",
37080
+ school_bus: "vehicle",
37081
+ garbage_truck: "vehicle",
37082
+ dog: "animal",
37083
+ cat: "animal",
37084
+ deer: "animal",
37085
+ horse: "animal",
37086
+ bird: "animal",
37087
+ raccoon: "animal",
37088
+ fox: "animal",
37089
+ bear: "animal",
37090
+ cow: "animal",
37091
+ squirrel: "animal",
37092
+ goat: "animal",
37093
+ rabbit: "animal",
37094
+ skunk: "animal",
37095
+ kangaroo: "animal",
37096
+ possum: "animal",
37097
+ rodent: "animal",
37098
+ package: "package"
37099
+ };
37100
+ /**
37101
+ * The per-model classMap for a Frigate / Frigate+ detector, derived from ITS
37102
+ * labelmap: each label resolves through {@link FRIGATE_PLUS_TO_MACRO} first,
37103
+ * then `COCO_TO_MACRO` (Frigate's default model ships the COCO-91 labelmap, so
37104
+ * a preset import may carry either vocabulary). A label neither knows is left
37105
+ * out, and `preserveOriginal: false` drops it in the executor — the same
37106
+ * contract as the COCO map, now with the Frigate+ vocabulary in it.
37107
+ */
37108
+ function buildFrigateClassMap(labels) {
37109
+ const mapping = {};
37110
+ for (const label of labels) {
37111
+ const target = FRIGATE_PLUS_TO_MACRO[label] ?? COCO_TO_MACRO.mapping[label];
37112
+ if (target !== void 0 && isClassMapMacroTarget(target)) mapping[label] = target;
37113
+ }
37114
+ return {
37115
+ mapping,
37116
+ preserveOriginal: false
37117
+ };
37118
+ }
37119
+ /**
37120
+ * Everything a Frigate / Frigate+ entry derives from its labelmap: the classMap
37121
+ * and the steps it fills (D715). Every Frigate builder spreads this, so the two
37122
+ * cannot be derived from different label lists. A COCO labelmap gets its map
37123
+ * and no fill.
37124
+ */
37125
+ function frigateLabelFields(labels) {
37126
+ const classMap = buildFrigateClassMap(labels);
37127
+ const fills = deriveClassifierFills(labels, classMap);
37128
+ return fills.length > 0 ? {
37129
+ classMap,
37130
+ fillsClassifierEffects: fills
37131
+ } : { classMap };
37132
+ }
36610
37133
  /**
36611
37134
  * Accessory device helpers — shared across drivers.
36612
37135
  *
@@ -48006,6 +48529,8 @@ new Map(Object.entries({
48006
48529
  "detection-blind": "device-events",
48007
48530
  "node-online": "system",
48008
48531
  "node-offline": "system",
48532
+ "node-restarting": "system",
48533
+ "node-updating": "system",
48009
48534
  "node-inference-unavailable": "system",
48010
48535
  "addon-crash-loop": "system",
48011
48536
  "addon-update-available": "system",
@@ -48083,6 +48608,7 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
48083
48608
  kinds: [
48084
48609
  "node-offline",
48085
48610
  "node-online",
48611
+ "node-restarting",
48086
48612
  "node-inference-unavailable"
48087
48613
  ]
48088
48614
  },
@@ -48104,6 +48630,7 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
48104
48630
  label: "Server & container updates",
48105
48631
  kinds: [
48106
48632
  "server-update-available",
48633
+ "node-updating",
48107
48634
  "server-updated",
48108
48635
  "wrapper-update-available"
48109
48636
  ]
@@ -48251,6 +48778,7 @@ var STATE_SUMMARY_SECTION_VARS = [
48251
48778
  kinds: [
48252
48779
  "node-offline",
48253
48780
  "node-online",
48781
+ "node-restarting",
48254
48782
  "node-inference-unavailable"
48255
48783
  ]
48256
48784
  },
@@ -48272,6 +48800,7 @@ var STATE_SUMMARY_SECTION_VARS = [
48272
48800
  example: "server 1.2.377 → 1.2.378",
48273
48801
  kinds: [
48274
48802
  "server-update-available",
48803
+ "node-updating",
48275
48804
  "server-updated",
48276
48805
  "wrapper-update-available"
48277
48806
  ]
@@ -49355,6 +49884,7 @@ function buildFrigateCatalogDescriptor(catalogId, overrides) {
49355
49884
  id: name,
49356
49885
  name
49357
49886
  })),
49887
+ ...frigateLabelFields(cat.labels),
49358
49888
  preprocessMode: "letterbox",
49359
49889
  provider: "frigate",
49360
49890
  license: cat.license,
@@ -49504,6 +50034,24 @@ async function ensureFormatsThenDistribute(modelId, deps) {
49504
50034
  }
49505
50035
  //#endregion
49506
50036
  //#region src/frigate/frigate-plus.ts
50037
+ /**
50038
+ * Frigate+ API client — the REAL api.frigate.video contract, verified against
50039
+ * frigate/plus.py (dev branch, 2026-08-21):
50040
+ *
50041
+ * - key format: `[uuid]:[40 hex]` (Frigate validates
50042
+ * `[a-z0-9]{8}-…-[a-z0-9]{12}:[a-z0-9]{40}`)
50043
+ * - GET /v1/auth/token with HTTP basic auth (key split on `:`) →
50044
+ * `{ accessToken, expires }`
50045
+ * - GET /v1/model/list with `Authorization: Bearer <accessToken>` → model list
50046
+ * - GET /v1/model/{id} → model info (`type`, `width`, `height`, `labelMap`,
50047
+ * `supportedDetectors`, …)
50048
+ * - GET /v1/model/{id}/signed_url → `{ url }` (presigned, plain GET)
50049
+ *
50050
+ * SECURITY: everything here runs SERVER-SIDE on the hub. The key comes from
50051
+ * the addon's settings store, is sent only to api.frigate.video, and is never
50052
+ * logged, never echoed in errors, never shipped to the browser. The fetch
50053
+ * function is injected so the contract is unit-testable offline.
50054
+ */
49507
50055
  var PLUS_API_HOST = "https://api.frigate.video";
49508
50056
  var PLUS_KEY_RE = /^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}:[a-z0-9]{40}$/;
49509
50057
  function isValidPlusApiKey(key) {
@@ -49678,6 +50226,7 @@ function plusInfoToDescriptor(info, opts) {
49678
50226
  id: name,
49679
50227
  name
49680
50228
  })),
50229
+ ...frigateLabelFields(labels),
49681
50230
  preprocessMode: "letterbox",
49682
50231
  provider: "frigate",
49683
50232
  group: frigateVariantGroup(info.type, info.width),