@camstack/addon-model-studio 1.1.200 → 1.1.202

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 +49 -43
  2. package/dist/{MotionZonesSettings-DXWpYKPD.mjs → MotionZonesSettings-qabihnVu.mjs} +2 -2
  3. package/dist/{PrivacyMaskSettings-BcaCmwR2.mjs → PrivacyMaskSettings-CGVI9EVl.mjs} +4 -4
  4. package/dist/{SceneMonitorEditor-D8IoPtTi.mjs → SceneMonitorEditor-BcAVb1c7.mjs} +3 -3
  5. package/dist/_stub.js +3928 -3904
  6. package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_model_studio_page-ChSw1hrV.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_model_studio_page-CZVL55Bi.mjs} +4 -4
  7. package/dist/_virtual_mf___mfe_internal__addon_model_studio_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DMrwYkbN.mjs +26 -0
  8. package/dist/{hostInit-TRVWPuo-.mjs → hostInit-D_0AEBSS.mjs} +3 -3
  9. package/dist/model-studio.addon.js +677 -73
  10. package/dist/model-studio.addon.mjs +677 -73
  11. package/dist/{player-overlays-4Vb0Si7c.mjs → player-overlays-CgZQeBdy.mjs} +1 -1
  12. package/dist/remoteEntry.js +1 -1
  13. package/dist/{responsive-D8JojVmZ.mjs → responsive-dgrtmGP7.mjs} +1 -1
  14. package/dist/{scene-monitor-copy-Cw3r5D6b.mjs → scene-monitor-copy-CWuj3twx.mjs} +1 -1
  15. package/dist/{square-C4Y02RV4.mjs → square-U1jjwP1Q.mjs} +1 -1
  16. package/dist/{trash-2-D-gDRhvd.mjs → trash-2-B3hyZ06m.mjs} +1 -1
  17. package/dist/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_model_studio_page__remoteEntry_js-Bs1AQFNt.mjs → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_model_studio_page__remoteEntry_js-Rw5qHN1M.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-C0rOztYh.mjs +0 -26
@@ -10900,6 +10900,478 @@ var ClipSearchStrictnessSchema = _enum([
10900
10900
  "balanced",
10901
10901
  "strict"
10902
10902
  ]);
10903
+ var COCO_80_LABELS = [
10904
+ {
10905
+ id: "person",
10906
+ name: "Person"
10907
+ },
10908
+ {
10909
+ id: "bicycle",
10910
+ name: "Bicycle"
10911
+ },
10912
+ {
10913
+ id: "car",
10914
+ name: "Car"
10915
+ },
10916
+ {
10917
+ id: "motorcycle",
10918
+ name: "Motorcycle"
10919
+ },
10920
+ {
10921
+ id: "airplane",
10922
+ name: "Airplane"
10923
+ },
10924
+ {
10925
+ id: "bus",
10926
+ name: "Bus"
10927
+ },
10928
+ {
10929
+ id: "train",
10930
+ name: "Train"
10931
+ },
10932
+ {
10933
+ id: "truck",
10934
+ name: "Truck"
10935
+ },
10936
+ {
10937
+ id: "boat",
10938
+ name: "Boat"
10939
+ },
10940
+ {
10941
+ id: "traffic light",
10942
+ name: "Traffic Light"
10943
+ },
10944
+ {
10945
+ id: "fire hydrant",
10946
+ name: "Fire Hydrant"
10947
+ },
10948
+ {
10949
+ id: "stop sign",
10950
+ name: "Stop Sign"
10951
+ },
10952
+ {
10953
+ id: "parking meter",
10954
+ name: "Parking Meter"
10955
+ },
10956
+ {
10957
+ id: "bench",
10958
+ name: "Bench"
10959
+ },
10960
+ {
10961
+ id: "bird",
10962
+ name: "Bird"
10963
+ },
10964
+ {
10965
+ id: "cat",
10966
+ name: "Cat"
10967
+ },
10968
+ {
10969
+ id: "dog",
10970
+ name: "Dog"
10971
+ },
10972
+ {
10973
+ id: "horse",
10974
+ name: "Horse"
10975
+ },
10976
+ {
10977
+ id: "sheep",
10978
+ name: "Sheep"
10979
+ },
10980
+ {
10981
+ id: "cow",
10982
+ name: "Cow"
10983
+ },
10984
+ {
10985
+ id: "elephant",
10986
+ name: "Elephant"
10987
+ },
10988
+ {
10989
+ id: "bear",
10990
+ name: "Bear"
10991
+ },
10992
+ {
10993
+ id: "zebra",
10994
+ name: "Zebra"
10995
+ },
10996
+ {
10997
+ id: "giraffe",
10998
+ name: "Giraffe"
10999
+ },
11000
+ {
11001
+ id: "backpack",
11002
+ name: "Backpack"
11003
+ },
11004
+ {
11005
+ id: "umbrella",
11006
+ name: "Umbrella"
11007
+ },
11008
+ {
11009
+ id: "handbag",
11010
+ name: "Handbag"
11011
+ },
11012
+ {
11013
+ id: "tie",
11014
+ name: "Tie"
11015
+ },
11016
+ {
11017
+ id: "suitcase",
11018
+ name: "Suitcase"
11019
+ },
11020
+ {
11021
+ id: "frisbee",
11022
+ name: "Frisbee"
11023
+ },
11024
+ {
11025
+ id: "skis",
11026
+ name: "Skis"
11027
+ },
11028
+ {
11029
+ id: "snowboard",
11030
+ name: "Snowboard"
11031
+ },
11032
+ {
11033
+ id: "sports ball",
11034
+ name: "Sports Ball"
11035
+ },
11036
+ {
11037
+ id: "kite",
11038
+ name: "Kite"
11039
+ },
11040
+ {
11041
+ id: "baseball bat",
11042
+ name: "Baseball Bat"
11043
+ },
11044
+ {
11045
+ id: "baseball glove",
11046
+ name: "Baseball Glove"
11047
+ },
11048
+ {
11049
+ id: "skateboard",
11050
+ name: "Skateboard"
11051
+ },
11052
+ {
11053
+ id: "surfboard",
11054
+ name: "Surfboard"
11055
+ },
11056
+ {
11057
+ id: "tennis racket",
11058
+ name: "Tennis Racket"
11059
+ },
11060
+ {
11061
+ id: "bottle",
11062
+ name: "Bottle"
11063
+ },
11064
+ {
11065
+ id: "wine glass",
11066
+ name: "Wine Glass"
11067
+ },
11068
+ {
11069
+ id: "cup",
11070
+ name: "Cup"
11071
+ },
11072
+ {
11073
+ id: "fork",
11074
+ name: "Fork"
11075
+ },
11076
+ {
11077
+ id: "knife",
11078
+ name: "Knife"
11079
+ },
11080
+ {
11081
+ id: "spoon",
11082
+ name: "Spoon"
11083
+ },
11084
+ {
11085
+ id: "bowl",
11086
+ name: "Bowl"
11087
+ },
11088
+ {
11089
+ id: "banana",
11090
+ name: "Banana"
11091
+ },
11092
+ {
11093
+ id: "apple",
11094
+ name: "Apple"
11095
+ },
11096
+ {
11097
+ id: "sandwich",
11098
+ name: "Sandwich"
11099
+ },
11100
+ {
11101
+ id: "orange",
11102
+ name: "Orange"
11103
+ },
11104
+ {
11105
+ id: "broccoli",
11106
+ name: "Broccoli"
11107
+ },
11108
+ {
11109
+ id: "carrot",
11110
+ name: "Carrot"
11111
+ },
11112
+ {
11113
+ id: "hot dog",
11114
+ name: "Hot Dog"
11115
+ },
11116
+ {
11117
+ id: "pizza",
11118
+ name: "Pizza"
11119
+ },
11120
+ {
11121
+ id: "donut",
11122
+ name: "Donut"
11123
+ },
11124
+ {
11125
+ id: "cake",
11126
+ name: "Cake"
11127
+ },
11128
+ {
11129
+ id: "chair",
11130
+ name: "Chair"
11131
+ },
11132
+ {
11133
+ id: "couch",
11134
+ name: "Couch"
11135
+ },
11136
+ {
11137
+ id: "potted plant",
11138
+ name: "Potted Plant"
11139
+ },
11140
+ {
11141
+ id: "bed",
11142
+ name: "Bed"
11143
+ },
11144
+ {
11145
+ id: "dining table",
11146
+ name: "Dining Table"
11147
+ },
11148
+ {
11149
+ id: "toilet",
11150
+ name: "Toilet"
11151
+ },
11152
+ {
11153
+ id: "tv",
11154
+ name: "TV"
11155
+ },
11156
+ {
11157
+ id: "laptop",
11158
+ name: "Laptop"
11159
+ },
11160
+ {
11161
+ id: "mouse",
11162
+ name: "Mouse"
11163
+ },
11164
+ {
11165
+ id: "remote",
11166
+ name: "Remote"
11167
+ },
11168
+ {
11169
+ id: "keyboard",
11170
+ name: "Keyboard"
11171
+ },
11172
+ {
11173
+ id: "cell phone",
11174
+ name: "Cell Phone"
11175
+ },
11176
+ {
11177
+ id: "microwave",
11178
+ name: "Microwave"
11179
+ },
11180
+ {
11181
+ id: "oven",
11182
+ name: "Oven"
11183
+ },
11184
+ {
11185
+ id: "toaster",
11186
+ name: "Toaster"
11187
+ },
11188
+ {
11189
+ id: "sink",
11190
+ name: "Sink"
11191
+ },
11192
+ {
11193
+ id: "refrigerator",
11194
+ name: "Refrigerator"
11195
+ },
11196
+ {
11197
+ id: "book",
11198
+ name: "Book"
11199
+ },
11200
+ {
11201
+ id: "clock",
11202
+ name: "Clock"
11203
+ },
11204
+ {
11205
+ id: "vase",
11206
+ name: "Vase"
11207
+ },
11208
+ {
11209
+ id: "scissors",
11210
+ name: "Scissors"
11211
+ },
11212
+ {
11213
+ id: "teddy bear",
11214
+ name: "Teddy Bear"
11215
+ },
11216
+ {
11217
+ id: "hair drier",
11218
+ name: "Hair Drier"
11219
+ },
11220
+ {
11221
+ id: "toothbrush",
11222
+ name: "Toothbrush"
11223
+ }
11224
+ ];
11225
+ new Set([
11226
+ {
11227
+ id: "person",
11228
+ name: "Person"
11229
+ },
11230
+ {
11231
+ id: "vehicle",
11232
+ name: "Vehicle"
11233
+ },
11234
+ {
11235
+ id: "animal",
11236
+ name: "Animal"
11237
+ },
11238
+ {
11239
+ id: "package",
11240
+ name: "Package"
11241
+ }
11242
+ ].map((l) => l.id));
11243
+ var COCO_TO_MACRO = {
11244
+ mapping: {
11245
+ person: "person",
11246
+ bicycle: "vehicle",
11247
+ car: "vehicle",
11248
+ motorcycle: "vehicle",
11249
+ airplane: "vehicle",
11250
+ bus: "vehicle",
11251
+ train: "vehicle",
11252
+ truck: "vehicle",
11253
+ boat: "vehicle",
11254
+ bird: "animal",
11255
+ cat: "animal",
11256
+ dog: "animal",
11257
+ horse: "animal",
11258
+ sheep: "animal",
11259
+ cow: "animal",
11260
+ elephant: "animal",
11261
+ bear: "animal",
11262
+ zebra: "animal",
11263
+ giraffe: "animal",
11264
+ suitcase: "package",
11265
+ backpack: "package",
11266
+ handbag: "package"
11267
+ },
11268
+ preserveOriginal: false
11269
+ };
11270
+ /** Steps a root detector may declare it fills. */
11271
+ var FILLABLE_STEP_IDS = [
11272
+ "animal-classifier",
11273
+ "vehicle-classifier",
11274
+ "package-detection"
11275
+ ];
11276
+ /**
11277
+ * The EFFECT vocabulary of each fillable step: exactly the strings the step
11278
+ * itself emits, in its own spelling. A linked label is one of these and nothing
11279
+ * else, so a tier-1 value means the same thing whichever writer produced it.
11280
+ *
11281
+ * - `animal-classifier`: the PRIMARY model's `-labels.json` (Open Images V7,
11282
+ * 8 classes) — also the species allow-list the step offers.
11283
+ * - `vehicle-classifier`: `vehicle-type-v1-labels.json`, capitalised as the
11284
+ * model emits them (the classifier writes `winner.class` verbatim).
11285
+ * - `package-detection`: its one output class.
11286
+ *
11287
+ * `scripts/check-label-link-vocabulary.ts` fails the build if a model entry's
11288
+ * `labelToEffect` names anything outside this table.
11289
+ */
11290
+ var FILLABLE_STEP_VOCABULARIES = {
11291
+ "animal-classifier": [
11292
+ "bird",
11293
+ "cat",
11294
+ "cow",
11295
+ "deer",
11296
+ "dog",
11297
+ "horse",
11298
+ "sheep",
11299
+ "squirrel"
11300
+ ],
11301
+ "vehicle-classifier": [
11302
+ "Ambulance",
11303
+ "Bicycle",
11304
+ "Bus",
11305
+ "Car",
11306
+ "Motorcycle",
11307
+ "Taxi",
11308
+ "Truck",
11309
+ "Van"
11310
+ ],
11311
+ "package-detection": ["package"]
11312
+ };
11313
+ /** The macro a detection must carry for the step to apply to it. */
11314
+ var FILLABLE_STEP_MACRO = {
11315
+ "animal-classifier": "animal",
11316
+ "vehicle-classifier": "vehicle",
11317
+ "package-detection": "package"
11318
+ };
11319
+ /**
11320
+ * Raw detector labels that name a vocabulary entry under another spelling.
11321
+ * Case-insensitive equality covers the rest (`car` → `Car`).
11322
+ */
11323
+ var EFFECT_ALIASES = {
11324
+ "animal-classifier": {},
11325
+ "vehicle-classifier": {
11326
+ school_bus: "Bus",
11327
+ garbage_truck: "Truck"
11328
+ },
11329
+ "package-detection": {}
11330
+ };
11331
+ /**
11332
+ * A labelmap is COCO when it carries at least half of the COCO-80 classes. A
11333
+ * COCO detector NEVER fills a step (operator decision, D715): its `dog` / `car`
11334
+ * is the generic class the classifier exists to refine, and its six animal
11335
+ * classes would otherwise read as "fills animal-classifier 6/8". Frigate+
11336
+ * shares about a dozen COCO names; a COCO-80 or COCO-91 labelmap carries ~80.
11337
+ */
11338
+ function isCocoLabelmap(labels) {
11339
+ const present = new Set(labels);
11340
+ return COCO_80_LABELS.filter((l) => present.has(l.id)).length * 2 >= COCO_80_LABELS.length;
11341
+ }
11342
+ function effectFor(stepId, label) {
11343
+ const alias = EFFECT_ALIASES[stepId][label];
11344
+ if (alias !== void 0) return alias;
11345
+ const folded = label.toLowerCase();
11346
+ return FILLABLE_STEP_VOCABULARIES[stepId].find((v) => v.toLowerCase() === folded);
11347
+ }
11348
+ /**
11349
+ * Which steps a root detector fills, from its labelmap and classMap. A label
11350
+ * counts for a step only when the model's classMap sends it to that step's
11351
+ * macro AND it names a vocabulary entry. A step none of the labels reach is
11352
+ * not declared; a COCO labelmap declares nothing.
11353
+ */
11354
+ function deriveClassifierFills(labels, classMap) {
11355
+ if (classMap === void 0 || isCocoLabelmap(labels)) return [];
11356
+ const fills = [];
11357
+ for (const stepId of FILLABLE_STEP_IDS) {
11358
+ const labelToEffect = {};
11359
+ for (const label of labels) {
11360
+ if (classMap.mapping[label] !== FILLABLE_STEP_MACRO[stepId]) continue;
11361
+ const effect = effectFor(stepId, label);
11362
+ if (effect !== void 0) labelToEffect[label] = effect;
11363
+ }
11364
+ const covered = new Set(Object.values(labelToEffect));
11365
+ if (covered.size === 0) continue;
11366
+ const uncovered = FILLABLE_STEP_VOCABULARIES[stepId].filter((v) => !covered.has(v));
11367
+ fills.push({
11368
+ stepId,
11369
+ labelToEffect,
11370
+ uncovered
11371
+ });
11372
+ }
11373
+ return fills;
11374
+ }
10903
11375
  var MODEL_FORMATS = [
10904
11376
  "onnx",
10905
11377
  "coreml",
@@ -11032,6 +11504,12 @@ var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { wei
11032
11504
  /** True when the weights or their data forbid commercial use. */
11033
11505
  nonCommercial: boolean().optional()
11034
11506
  }));
11507
+ /** One `fillsClassifierEffects` entry — see `ModelCatalogEntry.fillsClassifierEffects`. */
11508
+ var FillsClassifierEffectSchema = object({
11509
+ stepId: _enum(FILLABLE_STEP_IDS),
11510
+ labelToEffect: record(string(), string()),
11511
+ uncovered: array(string()).readonly()
11512
+ });
11035
11513
  var ModelCatalogEntrySchema = object({
11036
11514
  id: string(),
11037
11515
  name: string(),
@@ -11158,6 +11636,16 @@ var ModelCatalogEntrySchema = object({
11158
11636
  */
11159
11637
  classMap: DetectionCatalogClassMapSchema.optional(),
11160
11638
  /**
11639
+ * The pipeline steps this ROOT detector already does the work of (D715):
11640
+ * its labels name the effect the step exists to produce (`deer` for
11641
+ * `animal-classifier`, `package` for `package-detection`). Derived from the
11642
+ * labelmap by `deriveClassifierFills`, never hand-written; a COCO model
11643
+ * declares none. Whether a declaration is honoured is the step's own
11644
+ * `labelLink` policy (`resolveLabelLink`). `labelToEffect` values are in
11645
+ * `FILLABLE_STEP_VOCABULARIES` (guard `check-label-link-vocabulary`).
11646
+ */
11647
+ fillsClassifierEffects: array(FillsClassifierEffectSchema).readonly().optional(),
11648
+ /**
11161
11649
  * The model's CLIP feature-space contract (text encoder, dimension, vector
11162
11650
  * index, token window, search floor) — see `clip-model.ts`. Present ONLY on a
11163
11651
  * CLIP image encoder; its absence is what "not a CLIP model" means to the
@@ -14562,7 +15050,7 @@ DeviceType.Camera;
14562
15050
  * This matters here more than anywhere else in the repo, because every provider
14563
15051
  * that knows a device's host knows its PASSWORD too: `{ host, port, username,
14564
15052
  * password }` sit in one object on Hikvision, Amcrest, Reolink and ONVIF alike,
14565
- * and `http://admin:hunter2@192.168.x.x/` is a URL a browser accepts. The
15053
+ * and `http://admin:hunter2@192.168.60.139/` is a URL a browser accepts. The
14566
15054
  * camera's own page will ask for its own login. That is correct, and pre-
14567
15055
  * filling it is the operator's business, not ours.
14568
15056
  *
@@ -18118,51 +18606,6 @@ method(object({}), array(TargetKindSchema)), method(object({}), array(TargetSche
18118
18606
  kind: "mutation",
18119
18607
  auth: "admin"
18120
18608
  });
18121
- new Set([
18122
- {
18123
- id: "person",
18124
- name: "Person"
18125
- },
18126
- {
18127
- id: "vehicle",
18128
- name: "Vehicle"
18129
- },
18130
- {
18131
- id: "animal",
18132
- name: "Animal"
18133
- },
18134
- {
18135
- id: "package",
18136
- name: "Package"
18137
- }
18138
- ].map((l) => l.id));
18139
- var COCO_TO_MACRO = {
18140
- mapping: {
18141
- person: "person",
18142
- bicycle: "vehicle",
18143
- car: "vehicle",
18144
- motorcycle: "vehicle",
18145
- airplane: "vehicle",
18146
- bus: "vehicle",
18147
- train: "vehicle",
18148
- truck: "vehicle",
18149
- boat: "vehicle",
18150
- bird: "animal",
18151
- cat: "animal",
18152
- dog: "animal",
18153
- horse: "animal",
18154
- sheep: "animal",
18155
- cow: "animal",
18156
- elephant: "animal",
18157
- bear: "animal",
18158
- zebra: "animal",
18159
- giraffe: "animal",
18160
- suitcase: "package",
18161
- backpack: "package",
18162
- handbag: "package"
18163
- },
18164
- preserveOriginal: false
18165
- };
18166
18609
  var AUDIO_MACRO_LABELS = [
18167
18610
  {
18168
18611
  id: "speech",
@@ -20018,8 +20461,9 @@ var NcRuleSchema = NcRuleInputSchema.extend({
20018
20461
  disabledTargetIds: array(string()).default([])
20019
20462
  });
20020
20463
  /**
20021
- * The state-summary SECTIONS (D647 / D698): the D637 kind groups that report a
20022
- * still-true state. `backups-exports` and `alarm` are not sections — a completed
20464
+ * The state-summary SECTIONS (D647 / D698 / D708): the D637 kind groups that
20465
+ * report a still-true state. `addons` is the crash-looped addons only and
20466
+ * `addon-updates` the addons that are behind (D708 split them). `backups-exports` and `alarm` are not sections — a completed
20023
20467
  * job is not an open state, and the alarm stays instant.
20024
20468
  */
20025
20469
  var NcStateSummarySectionIdSchema = _enum([
@@ -20031,6 +20475,7 @@ var NcStateSummarySectionIdSchema = _enum([
20031
20475
  "detection-blind",
20032
20476
  "nodes",
20033
20477
  "addons",
20478
+ "addon-updates",
20034
20479
  "updates"
20035
20480
  ]);
20036
20481
  /** One section of a previewed state summary. `unavailable` = its state could not be read. */
@@ -20511,7 +20956,19 @@ var NcAlarmModeDelaysListSchema = array(object({
20511
20956
  * When this mode may be armed. Absent / null = always allowed (same as a
20512
20957
  * rule with no `schedule`). Evaluated with {@link isScheduleActive}.
20513
20958
  */
20514
- schedule: NcScheduleSchema.optional()
20959
+ schedule: NcScheduleSchema.optional(),
20960
+ /**
20961
+ * D706: while this mode's ENTRY DELAY runs, do the alarm rules' own pushes go out (as an
20962
+ * intrusion naming the locations)? Absent = false — the entry-delay notification is the
20963
+ * only one, and the matches ride the triggered notification's mosaic (D705).
20964
+ */
20965
+ notifyDuringEntryDelay: boolean().optional(),
20966
+ /**
20967
+ * D706: notify "watched again" when a sensor this arm bypassed closes and opens again.
20968
+ * Absent = false (logged, not sent). Even when true it is not sent when that same sensor
20969
+ * is the one that starts the entry delay — the entry-delay notification already names it.
20970
+ */
20971
+ notifySensorRewatched: boolean().optional()
20515
20972
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
20516
20973
  var NcAlarmModeDelaysEditListSchema = array(object({
20517
20974
  mode: AlarmArmModeSchema,
@@ -20520,7 +20977,11 @@ var NcAlarmModeDelaysEditListSchema = array(object({
20520
20977
  triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional(),
20521
20978
  postTriggeredAction: NcAlarmPostTriggeredActionSchema.nullable().optional(),
20522
20979
  /** Set a schedule, or `null` to clear (mode always allowed again). */
20523
- schedule: NcScheduleSchema.nullable().optional()
20980
+ schedule: NcScheduleSchema.nullable().optional(),
20981
+ /** D706: set the switch, or `null` to clear it (back to the default, false). */
20982
+ notifyDuringEntryDelay: boolean().nullable().optional(),
20983
+ /** D706: set the switch, or `null` to clear it (back to the default, false). */
20984
+ notifySensorRewatched: boolean().nullable().optional()
20524
20985
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
20525
20986
  /** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
20526
20987
  var NcAlarmNonBlockingEditSchema = object({
@@ -23548,7 +24009,8 @@ var PipelineModelOptionSchema = object({
23548
24009
  group: ModelVariantGroupSchema.optional(),
23549
24010
  legacy: boolean().optional(),
23550
24011
  provider: ModelProviderIdSchema.optional(),
23551
- defaultConfidence: number().optional()
24012
+ defaultConfidence: number().optional(),
24013
+ fillsClassifierEffects: array(FillsClassifierEffectSchema).readonly().optional()
23552
24014
  });
23553
24015
  var ConfigFieldBridge = custom();
23554
24016
  var PipelineAddonSchemaSchema = object({
@@ -24341,6 +24803,22 @@ var MotionSourceEnum = _enum([
24341
24803
  "device-activity"
24342
24804
  ]);
24343
24805
  /**
24806
+ * What opened an on-motion detection SESSION: the motion source that passed the
24807
+ * camera's `motionSources` gate, and what raised it (the camera itself, or a
24808
+ * sensor the operator attached — D672). `sensorName` is the attached sensor's
24809
+ * device name as the orchestrator's camera-sensors resolution last read it;
24810
+ * absent when unknown or when the camera itself triggered.
24811
+ *
24812
+ * Carried on the session attach ONLY so the runner's `DetectionPhaseTransition`
24813
+ * can say what started the session (D672 rule 11, amended 2026-10-06). The
24814
+ * runner never decides anything on it.
24815
+ */
24816
+ var SessionTriggerSchema = object({
24817
+ source: MotionSourceEnum,
24818
+ triggeredBy: MotionTriggeredBySchema,
24819
+ sensorName: string().optional()
24820
+ });
24821
+ /**
24344
24822
  * List of motion sources active on a camera. Empty array is valid:
24345
24823
  * "no source" — happens for battery cams without firmware motion when
24346
24824
  * the operator hasn't opted into the SW analyzer (would hold the
@@ -24592,6 +25070,14 @@ var RunnerCameraConfigSchema = object({
24592
25070
  */
24593
25071
  motionSources: MotionSourcesSchema.default(["analyzer"]),
24594
25072
  /**
25073
+ * What opened this attach, on a SESSION attach only (see
25074
+ * {@link SessionTriggerSchema}). OPTIONAL with no default: absent on a
25075
+ * standing attach, an occupancy burst, a re-dispatch with no motion event
25076
+ * behind it, and every attach from an orchestrator older than the field — the
25077
+ * runner then names no source on the phase event.
25078
+ */
25079
+ sessionTrigger: SessionTriggerSchema.optional(),
25080
+ /**
24595
25081
  * WHICH root detector runs for this camera. The detection counterpart of
24596
25082
  * {@link motionSources}, same shape and same discipline: a per-camera list
24597
25083
  * of sources the system understands, vendor-agnostic, owned here.
@@ -30815,7 +31301,7 @@ var LocalInterfaceSchema = object({
30815
31301
  name: string(),
30816
31302
  family: _enum(["IPv4", "IPv6"]),
30817
31303
  address: string(),
30818
- /** CIDR shorthand (e.g. `192.168.x.x/24`). Empty when OS doesn't expose. */
31304
+ /** CIDR shorthand (e.g. `192.168.10.10/24`). Empty when OS doesn't expose. */
30819
31305
  cidr: string(),
30820
31306
  /** OS netmask. Stable across calls so the SDK can hash on it. */
30821
31307
  netmask: string(),
@@ -30869,7 +31355,8 @@ var ConnectionEndpointSchema = object({
30869
31355
  "lan-ipv4",
30870
31356
  "lan-ipv6",
30871
31357
  "public",
30872
- "loopback"
31358
+ "loopback",
31359
+ "app-link"
30873
31360
  ]),
30874
31361
  /**
30875
31362
  * Originating-interface kind — `lan`/`wifi`/`docker`/`vpn`/`other`/
@@ -30938,15 +31425,27 @@ var GetConnectionEndpointsResultSchema = object({
30938
31425
  localPort: AdvertisedLocalPortSchema
30939
31426
  });
30940
31427
  /**
30941
- * The chosen outbound endpoint for notification artifacts. `baseUrl: null` =
30942
- * AUTO (resolved from the candidate ranking at send time); `resolved` reports
30943
- * what AUTO currently picks, so the UI can show the effective value either way.
31428
+ * The address flagged for notification links. `baseUrl: null` = AUTO, which
31429
+ * since D709 is the CamStack app link; `resolved` reports the effective value,
31430
+ * so the UI can show it either way.
30944
31431
  */
30945
31432
  var NotificationEndpointSchema = object({
30946
31433
  /** The operator's explicit choice, or null for AUTO. */
30947
31434
  baseUrl: string().nullable(),
30948
- /** What the ranking currently resolves to (null when nothing is reachable). */
30949
- resolved: string().nullable()
31435
+ /**
31436
+ * The effective flagged address: the explicit choice, else (AUTO) the
31437
+ * CamStack app link `https://camstack.zentik.app` (D709). A pre-D709 hub
31438
+ * answered the public tunnel / mesh here, or null.
31439
+ */
31440
+ resolved: string().nullable(),
31441
+ /**
31442
+ * The hub origin an app link carries as `hub=` (D709): the hub's best
31443
+ * public HTTPS address — the tunnel, then the mesh (Tailscale MagicDNS) —
31444
+ * picked from this cap's own palette by `pickAppLinkHub`. `null` when the
31445
+ * hub advertises neither; the app link is then minted without `hub=`.
31446
+ * Absent on a pre-D709 hub.
31447
+ */
31448
+ appLinkHub: string().nullable()
30950
31449
  });
30951
31450
  /**
30952
31451
  * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
@@ -31000,7 +31499,11 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
31000
31499
  * Pass `'https'` when the caller is itself loaded over HTTPS
31001
31500
  * to avoid mixed-content blocks in the browser. The public
31002
31501
  * tunnel always emits `https://` regardless. */
31003
- scheme: _enum(["http", "https"]).optional()
31502
+ scheme: _enum(["http", "https"]).optional(),
31503
+ /** Append the CamStack app link entry (`kind: 'app-link'`, D709) —
31504
+ * an address notification links can be flagged with, not a hub
31505
+ * route. Default `false`: racers and rankers never see it. */
31506
+ includeAppLink: boolean().optional()
31004
31507
  }), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), ViewerEndpointsSchema), method(object({ baseUrls: array(string()).readonly() }), ViewerEndpointsSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" }), method(_void(), TlsStatusSchema), method(object({ reason: string().optional() }), TlsStatusSchema, {
31005
31508
  kind: "mutation",
31006
31509
  auth: "admin"
@@ -31261,7 +31764,7 @@ var MeshPeerSchema = object({
31261
31764
  tags: array(string()).readonly(),
31262
31765
  /** True when the peer advertises itself as an exit-node candidate. */
31263
31766
  exitNodeOption: boolean(),
31264
- /** Subnet routes the peer advertises (e.g. `["192.168.x.x/24"]`). */
31767
+ /** Subnet routes the peer advertises (e.g. `["192.168.10.0/24"]`). */
31265
31768
  advertisedRoutes: array(string()).readonly(),
31266
31769
  /** Owner account login (e.g. `foo@example.com`). Null for tagged peers. */
31267
31770
  userLogin: string().nullable(),
@@ -36522,6 +37025,82 @@ DeviceType.Camera, method(object({
36522
37025
  package: array(ZoneRuleSchema).readonly()
36523
37026
  });
36524
37027
  SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
37028
+ function isClassMapMacroTarget(value) {
37029
+ return CLASS_MAP_MACRO_TARGETS.some((target) => target === value);
37030
+ }
37031
+ /**
37032
+ * Raw Frigate+ label → detection macro. Every label of the documented
37033
+ * Frigate+ base set (docs.frigate.video/plus, verified 2026-08-21) is either
37034
+ * here or in {@link FRIGATE_PLUS_UNMAPPED_LABELS}, with the reason it is not.
37035
+ *
37036
+ * Why this exists: a Frigate+ import used to carry NO classMap, so it inherited
37037
+ * the step's `COCO_TO_MACRO` (`preserveOriginal: false`) and the executor
37038
+ * dropped every label COCO does not name — deer, raccoon, fox, squirrel, goat,
37039
+ * rabbit, skunk, kangaroo, possum, rodent, school_bus, garbage_truck and even
37040
+ * `package` vanished as `class-filter` discards. The executor keeps the raw
37041
+ * label as `originalClass` whenever the map resolves it, so the fine identity
37042
+ * survives under the macro.
37043
+ */
37044
+ var FRIGATE_PLUS_TO_MACRO = {
37045
+ person: "person",
37046
+ baby: "person",
37047
+ car: "vehicle",
37048
+ motorcycle: "vehicle",
37049
+ bicycle: "vehicle",
37050
+ boat: "vehicle",
37051
+ school_bus: "vehicle",
37052
+ garbage_truck: "vehicle",
37053
+ dog: "animal",
37054
+ cat: "animal",
37055
+ deer: "animal",
37056
+ horse: "animal",
37057
+ bird: "animal",
37058
+ raccoon: "animal",
37059
+ fox: "animal",
37060
+ bear: "animal",
37061
+ cow: "animal",
37062
+ squirrel: "animal",
37063
+ goat: "animal",
37064
+ rabbit: "animal",
37065
+ skunk: "animal",
37066
+ kangaroo: "animal",
37067
+ possum: "animal",
37068
+ rodent: "animal",
37069
+ package: "package"
37070
+ };
37071
+ /**
37072
+ * The per-model classMap for a Frigate / Frigate+ detector, derived from ITS
37073
+ * labelmap: each label resolves through {@link FRIGATE_PLUS_TO_MACRO} first,
37074
+ * then `COCO_TO_MACRO` (Frigate's default model ships the COCO-91 labelmap, so
37075
+ * a preset import may carry either vocabulary). A label neither knows is left
37076
+ * out, and `preserveOriginal: false` drops it in the executor — the same
37077
+ * contract as the COCO map, now with the Frigate+ vocabulary in it.
37078
+ */
37079
+ function buildFrigateClassMap(labels) {
37080
+ const mapping = {};
37081
+ for (const label of labels) {
37082
+ const target = FRIGATE_PLUS_TO_MACRO[label] ?? COCO_TO_MACRO.mapping[label];
37083
+ if (target !== void 0 && isClassMapMacroTarget(target)) mapping[label] = target;
37084
+ }
37085
+ return {
37086
+ mapping,
37087
+ preserveOriginal: false
37088
+ };
37089
+ }
37090
+ /**
37091
+ * Everything a Frigate / Frigate+ entry derives from its labelmap: the classMap
37092
+ * and the steps it fills (D715). Every Frigate builder spreads this, so the two
37093
+ * cannot be derived from different label lists. A COCO labelmap gets its map
37094
+ * and no fill.
37095
+ */
37096
+ function frigateLabelFields(labels) {
37097
+ const classMap = buildFrigateClassMap(labels);
37098
+ const fills = deriveClassifierFills(labels, classMap);
37099
+ return fills.length > 0 ? {
37100
+ classMap,
37101
+ fillsClassifierEffects: fills
37102
+ } : { classMap };
37103
+ }
36525
37104
  /**
36526
37105
  * Accessory device helpers — shared across drivers.
36527
37106
  *
@@ -48004,12 +48583,14 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
48004
48583
  {
48005
48584
  id: "addons",
48006
48585
  family: "system",
48007
- label: "Addons",
48008
- kinds: [
48009
- "addon-crash-loop",
48010
- "addon-update-available",
48011
- "addon-updated"
48012
- ]
48586
+ label: "Addons stopped",
48587
+ kinds: ["addon-crash-loop"]
48588
+ },
48589
+ {
48590
+ id: "addon-updates",
48591
+ family: "system",
48592
+ label: "Addon updates",
48593
+ kinds: ["addon-update-available", "addon-updated"]
48013
48594
  },
48014
48595
  {
48015
48596
  id: "updates",
@@ -48169,13 +48750,15 @@ var STATE_SUMMARY_SECTION_VARS = [
48169
48750
  },
48170
48751
  {
48171
48752
  name: "summaryAddons",
48172
- label: "Summary: addons",
48173
- example: "@camstack/addon-recorder 1.2.3 → 1.2.4",
48174
- kinds: [
48175
- "addon-crash-loop",
48176
- "addon-update-available",
48177
- "addon-updated"
48178
- ]
48753
+ label: "Summary: addons stopped",
48754
+ example: "hub — recorder stopped after repeated crashes",
48755
+ kinds: ["addon-crash-loop"]
48756
+ },
48757
+ {
48758
+ name: "summaryAddonUpdates",
48759
+ label: "Summary: addon updates",
48760
+ example: "hub:\n• @camstack/addon-recorder 1.2.3 → 1.2.4",
48761
+ kinds: ["addon-update-available", "addon-updated"]
48179
48762
  },
48180
48763
  {
48181
48764
  name: "summaryUpdates",
@@ -48259,6 +48842,7 @@ var STATE_SUMMARY_VARS = [
48259
48842
  [...RULE_BODY_ONLY],
48260
48843
  [...RULE_TEXT],
48261
48844
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
48845
+ ([...RULE_TEXT], [...COMBINED_ALARM]),
48262
48846
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
48263
48847
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
48264
48848
  ([...RULE_TEXT], [...CONSUMABLE]),
@@ -49265,6 +49849,7 @@ function buildFrigateCatalogDescriptor(catalogId, overrides) {
49265
49849
  id: name,
49266
49850
  name
49267
49851
  })),
49852
+ ...frigateLabelFields(cat.labels),
49268
49853
  preprocessMode: "letterbox",
49269
49854
  provider: "frigate",
49270
49855
  license: cat.license,
@@ -49414,6 +49999,24 @@ async function ensureFormatsThenDistribute(modelId, deps) {
49414
49999
  }
49415
50000
  //#endregion
49416
50001
  //#region src/frigate/frigate-plus.ts
50002
+ /**
50003
+ * Frigate+ API client — the REAL api.frigate.video contract, verified against
50004
+ * frigate/plus.py (dev branch, 2026-08-21):
50005
+ *
50006
+ * - key format: `[uuid]:[40 hex]` (Frigate validates
50007
+ * `[a-z0-9]{8}-…-[a-z0-9]{12}:[a-z0-9]{40}`)
50008
+ * - GET /v1/auth/token with HTTP basic auth (key split on `:`) →
50009
+ * `{ accessToken, expires }`
50010
+ * - GET /v1/model/list with `Authorization: Bearer <accessToken>` → model list
50011
+ * - GET /v1/model/{id} → model info (`type`, `width`, `height`, `labelMap`,
50012
+ * `supportedDetectors`, …)
50013
+ * - GET /v1/model/{id}/signed_url → `{ url }` (presigned, plain GET)
50014
+ *
50015
+ * SECURITY: everything here runs SERVER-SIDE on the hub. The key comes from
50016
+ * the addon's settings store, is sent only to api.frigate.video, and is never
50017
+ * logged, never echoed in errors, never shipped to the browser. The fetch
50018
+ * function is injected so the contract is unit-testable offline.
50019
+ */
49417
50020
  var PLUS_API_HOST = "https://api.frigate.video";
49418
50021
  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}$/;
49419
50022
  function isValidPlusApiKey(key) {
@@ -49588,6 +50191,7 @@ function plusInfoToDescriptor(info, opts) {
49588
50191
  id: name,
49589
50192
  name
49590
50193
  })),
50194
+ ...frigateLabelFields(labels),
49591
50195
  preprocessMode: "letterbox",
49592
50196
  provider: "frigate",
49593
50197
  group: frigateVariantGroup(info.type, info.width),