@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
@@ -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
@@ -14588,7 +15076,7 @@ DeviceType.Camera;
14588
15076
  * This matters here more than anywhere else in the repo, because every provider
14589
15077
  * that knows a device's host knows its PASSWORD too: `{ host, port, username,
14590
15078
  * password }` sit in one object on Hikvision, Amcrest, Reolink and ONVIF alike,
14591
- * and `http://admin:hunter2@192.168.x.x/` is a URL a browser accepts. The
15079
+ * and `http://admin:hunter2@192.168.60.139/` is a URL a browser accepts. The
14592
15080
  * camera's own page will ask for its own login. That is correct, and pre-
14593
15081
  * filling it is the operator's business, not ours.
14594
15082
  *
@@ -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",
@@ -20044,8 +20487,9 @@ var NcRuleSchema = NcRuleInputSchema.extend({
20044
20487
  disabledTargetIds: array(string()).default([])
20045
20488
  });
20046
20489
  /**
20047
- * The state-summary SECTIONS (D647 / D698): the D637 kind groups that report a
20048
- * still-true state. `backups-exports` and `alarm` are not sections — a completed
20490
+ * The state-summary SECTIONS (D647 / D698 / D708): the D637 kind groups that
20491
+ * report a still-true state. `addons` is the crash-looped addons only and
20492
+ * `addon-updates` the addons that are behind (D708 split them). `backups-exports` and `alarm` are not sections — a completed
20049
20493
  * job is not an open state, and the alarm stays instant.
20050
20494
  */
20051
20495
  var NcStateSummarySectionIdSchema = _enum([
@@ -20057,6 +20501,7 @@ var NcStateSummarySectionIdSchema = _enum([
20057
20501
  "detection-blind",
20058
20502
  "nodes",
20059
20503
  "addons",
20504
+ "addon-updates",
20060
20505
  "updates"
20061
20506
  ]);
20062
20507
  /** One section of a previewed state summary. `unavailable` = its state could not be read. */
@@ -20537,7 +20982,19 @@ var NcAlarmModeDelaysListSchema = array(object({
20537
20982
  * When this mode may be armed. Absent / null = always allowed (same as a
20538
20983
  * rule with no `schedule`). Evaluated with {@link isScheduleActive}.
20539
20984
  */
20540
- schedule: NcScheduleSchema.optional()
20985
+ schedule: NcScheduleSchema.optional(),
20986
+ /**
20987
+ * D706: while this mode's ENTRY DELAY runs, do the alarm rules' own pushes go out (as an
20988
+ * intrusion naming the locations)? Absent = false — the entry-delay notification is the
20989
+ * only one, and the matches ride the triggered notification's mosaic (D705).
20990
+ */
20991
+ notifyDuringEntryDelay: boolean().optional(),
20992
+ /**
20993
+ * D706: notify "watched again" when a sensor this arm bypassed closes and opens again.
20994
+ * Absent = false (logged, not sent). Even when true it is not sent when that same sensor
20995
+ * is the one that starts the entry delay — the entry-delay notification already names it.
20996
+ */
20997
+ notifySensorRewatched: boolean().optional()
20541
20998
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
20542
20999
  var NcAlarmModeDelaysEditListSchema = array(object({
20543
21000
  mode: AlarmArmModeSchema,
@@ -20546,7 +21003,11 @@ var NcAlarmModeDelaysEditListSchema = array(object({
20546
21003
  triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional(),
20547
21004
  postTriggeredAction: NcAlarmPostTriggeredActionSchema.nullable().optional(),
20548
21005
  /** Set a schedule, or `null` to clear (mode always allowed again). */
20549
- schedule: NcScheduleSchema.nullable().optional()
21006
+ schedule: NcScheduleSchema.nullable().optional(),
21007
+ /** D706: set the switch, or `null` to clear it (back to the default, false). */
21008
+ notifyDuringEntryDelay: boolean().nullable().optional(),
21009
+ /** D706: set the switch, or `null` to clear it (back to the default, false). */
21010
+ notifySensorRewatched: boolean().nullable().optional()
20550
21011
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
20551
21012
  /** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
20552
21013
  var NcAlarmNonBlockingEditSchema = object({
@@ -23574,7 +24035,8 @@ var PipelineModelOptionSchema = object({
23574
24035
  group: ModelVariantGroupSchema.optional(),
23575
24036
  legacy: boolean().optional(),
23576
24037
  provider: ModelProviderIdSchema.optional(),
23577
- defaultConfidence: number().optional()
24038
+ defaultConfidence: number().optional(),
24039
+ fillsClassifierEffects: array(FillsClassifierEffectSchema).readonly().optional()
23578
24040
  });
23579
24041
  var ConfigFieldBridge = custom();
23580
24042
  var PipelineAddonSchemaSchema = object({
@@ -24367,6 +24829,22 @@ var MotionSourceEnum = _enum([
24367
24829
  "device-activity"
24368
24830
  ]);
24369
24831
  /**
24832
+ * What opened an on-motion detection SESSION: the motion source that passed the
24833
+ * camera's `motionSources` gate, and what raised it (the camera itself, or a
24834
+ * sensor the operator attached — D672). `sensorName` is the attached sensor's
24835
+ * device name as the orchestrator's camera-sensors resolution last read it;
24836
+ * absent when unknown or when the camera itself triggered.
24837
+ *
24838
+ * Carried on the session attach ONLY so the runner's `DetectionPhaseTransition`
24839
+ * can say what started the session (D672 rule 11, amended 2026-10-06). The
24840
+ * runner never decides anything on it.
24841
+ */
24842
+ var SessionTriggerSchema = object({
24843
+ source: MotionSourceEnum,
24844
+ triggeredBy: MotionTriggeredBySchema,
24845
+ sensorName: string().optional()
24846
+ });
24847
+ /**
24370
24848
  * List of motion sources active on a camera. Empty array is valid:
24371
24849
  * "no source" — happens for battery cams without firmware motion when
24372
24850
  * the operator hasn't opted into the SW analyzer (would hold the
@@ -24618,6 +25096,14 @@ var RunnerCameraConfigSchema = object({
24618
25096
  */
24619
25097
  motionSources: MotionSourcesSchema.default(["analyzer"]),
24620
25098
  /**
25099
+ * What opened this attach, on a SESSION attach only (see
25100
+ * {@link SessionTriggerSchema}). OPTIONAL with no default: absent on a
25101
+ * standing attach, an occupancy burst, a re-dispatch with no motion event
25102
+ * behind it, and every attach from an orchestrator older than the field — the
25103
+ * runner then names no source on the phase event.
25104
+ */
25105
+ sessionTrigger: SessionTriggerSchema.optional(),
25106
+ /**
24621
25107
  * WHICH root detector runs for this camera. The detection counterpart of
24622
25108
  * {@link motionSources}, same shape and same discipline: a per-camera list
24623
25109
  * of sources the system understands, vendor-agnostic, owned here.
@@ -30841,7 +31327,7 @@ var LocalInterfaceSchema = object({
30841
31327
  name: string(),
30842
31328
  family: _enum(["IPv4", "IPv6"]),
30843
31329
  address: string(),
30844
- /** CIDR shorthand (e.g. `192.168.x.x/24`). Empty when OS doesn't expose. */
31330
+ /** CIDR shorthand (e.g. `192.168.10.10/24`). Empty when OS doesn't expose. */
30845
31331
  cidr: string(),
30846
31332
  /** OS netmask. Stable across calls so the SDK can hash on it. */
30847
31333
  netmask: string(),
@@ -30895,7 +31381,8 @@ var ConnectionEndpointSchema = object({
30895
31381
  "lan-ipv4",
30896
31382
  "lan-ipv6",
30897
31383
  "public",
30898
- "loopback"
31384
+ "loopback",
31385
+ "app-link"
30899
31386
  ]),
30900
31387
  /**
30901
31388
  * Originating-interface kind — `lan`/`wifi`/`docker`/`vpn`/`other`/
@@ -30964,15 +31451,27 @@ var GetConnectionEndpointsResultSchema = object({
30964
31451
  localPort: AdvertisedLocalPortSchema
30965
31452
  });
30966
31453
  /**
30967
- * The chosen outbound endpoint for notification artifacts. `baseUrl: null` =
30968
- * AUTO (resolved from the candidate ranking at send time); `resolved` reports
30969
- * what AUTO currently picks, so the UI can show the effective value either way.
31454
+ * The address flagged for notification links. `baseUrl: null` = AUTO, which
31455
+ * since D709 is the CamStack app link; `resolved` reports the effective value,
31456
+ * so the UI can show it either way.
30970
31457
  */
30971
31458
  var NotificationEndpointSchema = object({
30972
31459
  /** The operator's explicit choice, or null for AUTO. */
30973
31460
  baseUrl: string().nullable(),
30974
- /** What the ranking currently resolves to (null when nothing is reachable). */
30975
- resolved: string().nullable()
31461
+ /**
31462
+ * The effective flagged address: the explicit choice, else (AUTO) the
31463
+ * CamStack app link `https://camstack.zentik.app` (D709). A pre-D709 hub
31464
+ * answered the public tunnel / mesh here, or null.
31465
+ */
31466
+ resolved: string().nullable(),
31467
+ /**
31468
+ * The hub origin an app link carries as `hub=` (D709): the hub's best
31469
+ * public HTTPS address — the tunnel, then the mesh (Tailscale MagicDNS) —
31470
+ * picked from this cap's own palette by `pickAppLinkHub`. `null` when the
31471
+ * hub advertises neither; the app link is then minted without `hub=`.
31472
+ * Absent on a pre-D709 hub.
31473
+ */
31474
+ appLinkHub: string().nullable()
30976
31475
  });
30977
31476
  /**
30978
31477
  * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
@@ -31026,7 +31525,11 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
31026
31525
  * Pass `'https'` when the caller is itself loaded over HTTPS
31027
31526
  * to avoid mixed-content blocks in the browser. The public
31028
31527
  * tunnel always emits `https://` regardless. */
31029
- scheme: _enum(["http", "https"]).optional()
31528
+ scheme: _enum(["http", "https"]).optional(),
31529
+ /** Append the CamStack app link entry (`kind: 'app-link'`, D709) —
31530
+ * an address notification links can be flagged with, not a hub
31531
+ * route. Default `false`: racers and rankers never see it. */
31532
+ includeAppLink: boolean().optional()
31030
31533
  }), 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, {
31031
31534
  kind: "mutation",
31032
31535
  auth: "admin"
@@ -31287,7 +31790,7 @@ var MeshPeerSchema = object({
31287
31790
  tags: array(string()).readonly(),
31288
31791
  /** True when the peer advertises itself as an exit-node candidate. */
31289
31792
  exitNodeOption: boolean(),
31290
- /** Subnet routes the peer advertises (e.g. `["192.168.x.x/24"]`). */
31793
+ /** Subnet routes the peer advertises (e.g. `["192.168.10.0/24"]`). */
31291
31794
  advertisedRoutes: array(string()).readonly(),
31292
31795
  /** Owner account login (e.g. `foo@example.com`). Null for tagged peers. */
31293
31796
  userLogin: string().nullable(),
@@ -36548,6 +37051,82 @@ DeviceType.Camera, method(object({
36548
37051
  package: array(ZoneRuleSchema).readonly()
36549
37052
  });
36550
37053
  SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
37054
+ function isClassMapMacroTarget(value) {
37055
+ return CLASS_MAP_MACRO_TARGETS.some((target) => target === value);
37056
+ }
37057
+ /**
37058
+ * Raw Frigate+ label → detection macro. Every label of the documented
37059
+ * Frigate+ base set (docs.frigate.video/plus, verified 2026-08-21) is either
37060
+ * here or in {@link FRIGATE_PLUS_UNMAPPED_LABELS}, with the reason it is not.
37061
+ *
37062
+ * Why this exists: a Frigate+ import used to carry NO classMap, so it inherited
37063
+ * the step's `COCO_TO_MACRO` (`preserveOriginal: false`) and the executor
37064
+ * dropped every label COCO does not name — deer, raccoon, fox, squirrel, goat,
37065
+ * rabbit, skunk, kangaroo, possum, rodent, school_bus, garbage_truck and even
37066
+ * `package` vanished as `class-filter` discards. The executor keeps the raw
37067
+ * label as `originalClass` whenever the map resolves it, so the fine identity
37068
+ * survives under the macro.
37069
+ */
37070
+ var FRIGATE_PLUS_TO_MACRO = {
37071
+ person: "person",
37072
+ baby: "person",
37073
+ car: "vehicle",
37074
+ motorcycle: "vehicle",
37075
+ bicycle: "vehicle",
37076
+ boat: "vehicle",
37077
+ school_bus: "vehicle",
37078
+ garbage_truck: "vehicle",
37079
+ dog: "animal",
37080
+ cat: "animal",
37081
+ deer: "animal",
37082
+ horse: "animal",
37083
+ bird: "animal",
37084
+ raccoon: "animal",
37085
+ fox: "animal",
37086
+ bear: "animal",
37087
+ cow: "animal",
37088
+ squirrel: "animal",
37089
+ goat: "animal",
37090
+ rabbit: "animal",
37091
+ skunk: "animal",
37092
+ kangaroo: "animal",
37093
+ possum: "animal",
37094
+ rodent: "animal",
37095
+ package: "package"
37096
+ };
37097
+ /**
37098
+ * The per-model classMap for a Frigate / Frigate+ detector, derived from ITS
37099
+ * labelmap: each label resolves through {@link FRIGATE_PLUS_TO_MACRO} first,
37100
+ * then `COCO_TO_MACRO` (Frigate's default model ships the COCO-91 labelmap, so
37101
+ * a preset import may carry either vocabulary). A label neither knows is left
37102
+ * out, and `preserveOriginal: false` drops it in the executor — the same
37103
+ * contract as the COCO map, now with the Frigate+ vocabulary in it.
37104
+ */
37105
+ function buildFrigateClassMap(labels) {
37106
+ const mapping = {};
37107
+ for (const label of labels) {
37108
+ const target = FRIGATE_PLUS_TO_MACRO[label] ?? COCO_TO_MACRO.mapping[label];
37109
+ if (target !== void 0 && isClassMapMacroTarget(target)) mapping[label] = target;
37110
+ }
37111
+ return {
37112
+ mapping,
37113
+ preserveOriginal: false
37114
+ };
37115
+ }
37116
+ /**
37117
+ * Everything a Frigate / Frigate+ entry derives from its labelmap: the classMap
37118
+ * and the steps it fills (D715). Every Frigate builder spreads this, so the two
37119
+ * cannot be derived from different label lists. A COCO labelmap gets its map
37120
+ * and no fill.
37121
+ */
37122
+ function frigateLabelFields(labels) {
37123
+ const classMap = buildFrigateClassMap(labels);
37124
+ const fills = deriveClassifierFills(labels, classMap);
37125
+ return fills.length > 0 ? {
37126
+ classMap,
37127
+ fillsClassifierEffects: fills
37128
+ } : { classMap };
37129
+ }
36551
37130
  /**
36552
37131
  * Accessory device helpers — shared across drivers.
36553
37132
  *
@@ -48030,12 +48609,14 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
48030
48609
  {
48031
48610
  id: "addons",
48032
48611
  family: "system",
48033
- label: "Addons",
48034
- kinds: [
48035
- "addon-crash-loop",
48036
- "addon-update-available",
48037
- "addon-updated"
48038
- ]
48612
+ label: "Addons stopped",
48613
+ kinds: ["addon-crash-loop"]
48614
+ },
48615
+ {
48616
+ id: "addon-updates",
48617
+ family: "system",
48618
+ label: "Addon updates",
48619
+ kinds: ["addon-update-available", "addon-updated"]
48039
48620
  },
48040
48621
  {
48041
48622
  id: "updates",
@@ -48195,13 +48776,15 @@ var STATE_SUMMARY_SECTION_VARS = [
48195
48776
  },
48196
48777
  {
48197
48778
  name: "summaryAddons",
48198
- label: "Summary: addons",
48199
- example: "@camstack/addon-recorder 1.2.3 → 1.2.4",
48200
- kinds: [
48201
- "addon-crash-loop",
48202
- "addon-update-available",
48203
- "addon-updated"
48204
- ]
48779
+ label: "Summary: addons stopped",
48780
+ example: "hub — recorder stopped after repeated crashes",
48781
+ kinds: ["addon-crash-loop"]
48782
+ },
48783
+ {
48784
+ name: "summaryAddonUpdates",
48785
+ label: "Summary: addon updates",
48786
+ example: "hub:\n• @camstack/addon-recorder 1.2.3 → 1.2.4",
48787
+ kinds: ["addon-update-available", "addon-updated"]
48205
48788
  },
48206
48789
  {
48207
48790
  name: "summaryUpdates",
@@ -48285,6 +48868,7 @@ var STATE_SUMMARY_VARS = [
48285
48868
  [...RULE_BODY_ONLY],
48286
48869
  [...RULE_TEXT],
48287
48870
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
48871
+ ([...RULE_TEXT], [...COMBINED_ALARM]),
48288
48872
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
48289
48873
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
48290
48874
  ([...RULE_TEXT], [...CONSUMABLE]),
@@ -49291,6 +49875,7 @@ function buildFrigateCatalogDescriptor(catalogId, overrides) {
49291
49875
  id: name,
49292
49876
  name
49293
49877
  })),
49878
+ ...frigateLabelFields(cat.labels),
49294
49879
  preprocessMode: "letterbox",
49295
49880
  provider: "frigate",
49296
49881
  license: cat.license,
@@ -49440,6 +50025,24 @@ async function ensureFormatsThenDistribute(modelId, deps) {
49440
50025
  }
49441
50026
  //#endregion
49442
50027
  //#region src/frigate/frigate-plus.ts
50028
+ /**
50029
+ * Frigate+ API client — the REAL api.frigate.video contract, verified against
50030
+ * frigate/plus.py (dev branch, 2026-08-21):
50031
+ *
50032
+ * - key format: `[uuid]:[40 hex]` (Frigate validates
50033
+ * `[a-z0-9]{8}-…-[a-z0-9]{12}:[a-z0-9]{40}`)
50034
+ * - GET /v1/auth/token with HTTP basic auth (key split on `:`) →
50035
+ * `{ accessToken, expires }`
50036
+ * - GET /v1/model/list with `Authorization: Bearer <accessToken>` → model list
50037
+ * - GET /v1/model/{id} → model info (`type`, `width`, `height`, `labelMap`,
50038
+ * `supportedDetectors`, …)
50039
+ * - GET /v1/model/{id}/signed_url → `{ url }` (presigned, plain GET)
50040
+ *
50041
+ * SECURITY: everything here runs SERVER-SIDE on the hub. The key comes from
50042
+ * the addon's settings store, is sent only to api.frigate.video, and is never
50043
+ * logged, never echoed in errors, never shipped to the browser. The fetch
50044
+ * function is injected so the contract is unit-testable offline.
50045
+ */
49443
50046
  var PLUS_API_HOST = "https://api.frigate.video";
49444
50047
  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}$/;
49445
50048
  function isValidPlusApiKey(key) {
@@ -49614,6 +50217,7 @@ function plusInfoToDescriptor(info, opts) {
49614
50217
  id: name,
49615
50218
  name
49616
50219
  })),
50220
+ ...frigateLabelFields(labels),
49617
50221
  preprocessMode: "letterbox",
49618
50222
  provider: "frigate",
49619
50223
  group: frigateVariantGroup(info.type, info.width),