@camstack/addon-pipeline 1.2.628 → 1.2.629

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 (37) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +35 -0
  3. package/dist/audio-analyzer/index.js +3 -3
  4. package/dist/audio-analyzer/index.mjs +3 -3
  5. package/dist/{custom-model-catalog-Bu1Lc-iF.mjs → custom-model-catalog--z5qDAbz.mjs} +2 -2
  6. package/dist/{custom-model-catalog-D2oFV46F.js → custom-model-catalog-DyFqiWQw.js} +2 -2
  7. package/dist/detection-pipeline/index.js +4 -4
  8. package/dist/detection-pipeline/index.mjs +4 -4
  9. package/dist/{dist-DNW4WfVK.mjs → dist-DkFeDO1Z.mjs} +585 -12
  10. package/dist/{dist-BjySFF52.js → dist-vvIUo4Fg.js} +585 -12
  11. package/dist/{model-catalogs-CCHnV0wA.mjs → model-catalogs-DcAtdzQX.mjs} +1 -1
  12. package/dist/{model-catalogs-CwuCl3IY.js → model-catalogs-dHtp4VIV.js} +1 -1
  13. package/dist/motion-wasm/index.js +1 -1
  14. package/dist/motion-wasm/index.mjs +1 -1
  15. package/dist/{node-CiT7lJCO.mjs → node-CT-ETMWK.mjs} +1 -1
  16. package/dist/{node-CLDkYxRi.js → node-j-hM0LYt.js} +1 -1
  17. package/dist/pipeline-runner/index.js +3 -3
  18. package/dist/pipeline-runner/index.mjs +3 -3
  19. package/dist/{process-memory-D5WNQP42.js → process-memory-B9lUUQZw.js} +1 -1
  20. package/dist/{process-memory-6dtW_uwK.mjs → process-memory-BwZIeAKw.mjs} +1 -1
  21. package/dist/recorder/index.js +2 -2
  22. package/dist/recorder/index.mjs +2 -2
  23. package/dist/{segment-demux-js-DDI4hgPB.js → segment-demux-js-BCBpOp5j.js} +1 -1
  24. package/dist/{segment-demux-js-CL6CBu1v.mjs → segment-demux-js-CW7aiIml.mjs} +1 -1
  25. package/dist/stream-broker/_stub.js +2 -2
  26. package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DrEPZZ6A.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DUUHEAPV.mjs} +2 -2
  27. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BQMKjVwR.mjs +26 -0
  28. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-Ca0Qmh7u.mjs +26 -0
  29. package/dist/stream-broker/demux-worker-child.js +1 -1
  30. package/dist/stream-broker/demux-worker-child.mjs +1 -1
  31. package/dist/stream-broker/{hostInit-CsSJvo8w.mjs → hostInit-BiqKaq23.mjs} +2 -2
  32. package/dist/stream-broker/index.js +3 -3
  33. package/dist/stream-broker/index.mjs +3 -3
  34. package/dist/stream-broker/remoteEntry.js +1 -1
  35. package/package.json +4 -2
  36. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-aLQXb88Y.mjs +0 -26
  37. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CEiM-boT.mjs +0 -26
@@ -1,5 +1,5 @@
1
1
  import { createHash } from "node:crypto";
2
- //#region ../types/dist/event-category-DHXxB8t9.mjs
2
+ //#region ../types/dist/event-category-CT-hz5Rb.mjs
3
3
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4
4
  EventCategory["SystemBoot"] = "system.boot";
5
5
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -325,6 +325,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
325
325
  /** The recovery edge of {@link PipelineMotionNoisy}: the motion fell back, or a detection arrived. */
326
326
  EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
327
327
  /**
328
+ * A camera's package LLM confirm has failed closed three times in a row
329
+ * (D931, 2026-10-26). One edge per camera until
330
+ * {@link PipelinePackageLlmAnswered}.
331
+ */
332
+ EventCategory["PipelinePackageLlmSilent"] = "pipeline.package-llm-silent";
333
+ /** The recovery edge of {@link PipelinePackageLlmSilent}: a confirm returned yes or no. */
334
+ EventCategory["PipelinePackageLlmAnswered"] = "pipeline.package-llm-answered";
335
+ /**
328
336
  * Per-camera pipeline config was mutated by the orchestrator
329
337
  * (a settings change via `setAgentInferenceDevices` /
330
338
  * `setCameraStepToggle` / `setCameraStepSettings`). Orchestrator
@@ -5567,7 +5575,7 @@ var ZodIssueCode = {
5567
5575
  var ZodFirstPartyTypeKind;
5568
5576
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5569
5577
  //#endregion
5570
- //#region ../types/dist/sleep-CARd6wZF.mjs
5578
+ //#region ../types/dist/sleep-bykKrTgu.mjs
5571
5579
  /**
5572
5580
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5573
5581
  * window to float samples (D455).
@@ -8354,6 +8362,53 @@ var READING_QUANTITIES = [
8354
8362
  ];
8355
8363
  var ReadingQuantitySchema = _enum(READING_QUANTITIES);
8356
8364
  new Set(READING_QUANTITIES);
8365
+ /**
8366
+ * Stored unit symbol for a quantity. `none` means the number is dimensionless
8367
+ * (or an index / ratio / count). `device` means the cap has no single unit.
8368
+ */
8369
+ var QUANTITY_BASE = {
8370
+ temperature: "°C",
8371
+ pressure: "hPa",
8372
+ speed: "m/s",
8373
+ precipitation: "mm",
8374
+ "precipitation-rate": "mm/h",
8375
+ length: "m",
8376
+ area: "m²",
8377
+ illuminance: "lx",
8378
+ irradiance: "W/m²",
8379
+ power: "W",
8380
+ energy: "kWh",
8381
+ voltage: "V",
8382
+ current: "A",
8383
+ "apparent-power": "VA",
8384
+ humidity: "%",
8385
+ percentage: "%",
8386
+ "concentration-volume": "ppm",
8387
+ "concentration-mass": "µg/m³",
8388
+ "concentration-ppb": "ppb",
8389
+ volume: "L",
8390
+ duration: "s",
8391
+ "duration-ms": "ms",
8392
+ information: "B",
8393
+ "sound-level": "dBFS",
8394
+ "signal-level": "dBm",
8395
+ "colour-temperature": "mired",
8396
+ angle: "°",
8397
+ bitrate: "kbps",
8398
+ rate: "fps",
8399
+ mass: "kg",
8400
+ index: "none",
8401
+ ratio: "none",
8402
+ count: "none",
8403
+ none: "none",
8404
+ device: "device"
8405
+ };
8406
+ /** The stored unit, or `undefined` when the quantity has no unit symbol. */
8407
+ function baseUnitOf(quantity) {
8408
+ const symbol = QUANTITY_BASE[quantity];
8409
+ if (symbol === "none" || symbol === "device") return void 0;
8410
+ return symbol;
8411
+ }
8357
8412
  function readingMeta(quantity, extras) {
8358
8413
  return {
8359
8414
  quantity,
@@ -9052,6 +9107,8 @@ var CAP_NAMES = Object.freeze([
9052
9107
  "filesystem-browse",
9053
9108
  "flood",
9054
9109
  "gas",
9110
+ "group-commands",
9111
+ "group-status",
9055
9112
  "heating-valve",
9056
9113
  "humidifier",
9057
9114
  "humidity-sensor",
@@ -9870,6 +9927,20 @@ Object.freeze({
9870
9927
  "path": "detected",
9871
9928
  "valueType": "boolean"
9872
9929
  }],
9930
+ "group-status": [
9931
+ {
9932
+ "path": "included",
9933
+ "valueType": "number"
9934
+ },
9935
+ {
9936
+ "path": "excluded",
9937
+ "valueType": "number"
9938
+ },
9939
+ {
9940
+ "path": "total",
9941
+ "valueType": "number"
9942
+ }
9943
+ ],
9873
9944
  "heating-valve": [{
9874
9945
  "path": "position",
9875
9946
  "valueType": "number"
@@ -11363,7 +11434,7 @@ function errMsg(err) {
11363
11434
  return String(err);
11364
11435
  }
11365
11436
  //#endregion
11366
- //#region ../types/dist/composition-kEl9mevu.mjs
11437
+ //#region ../types/dist/composition-OhpuespA.mjs
11367
11438
  var AUDIO_ENCODER_BY_CODEC = {
11368
11439
  opus: "libopus",
11369
11440
  aac: "aac",
@@ -12954,15 +13025,74 @@ function validateExpressionSource(src) {
12954
13025
  }
12955
13026
  return null;
12956
13027
  }
12957
- /** A composed device's stableId is this prefix plus the block id. */
12958
- var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
12959
- /** Longest snippet a `code` source may carry (slice 4). */
12960
- var MAX_COMPOSITION_CODE_LENGTH = 2e4;
13028
+ /**
13029
+ * A composition source identity: `(addonId, stableId)`, never a numeric device
13030
+ * id. Split out so helper schemas can name it without a cycle through
13031
+ * `composition.ts` (D659).
13032
+ */
12961
13033
  var CompositionSourceRefSchema = object({
12962
13034
  /** The owning addon; `stableId` is unique only within it. */
12963
13035
  addonId: string().min(1),
12964
13036
  stableId: string().min(1)
12965
13037
  });
13038
+ var GROUP_TEMPLATE_IDS = [
13039
+ "temperature",
13040
+ "humidity",
13041
+ "pressure",
13042
+ "illuminance",
13043
+ "power",
13044
+ "energy",
13045
+ "battery",
13046
+ "numeric",
13047
+ "motion",
13048
+ "contact",
13049
+ "leak",
13050
+ "smoke",
13051
+ "occupancy",
13052
+ "binary",
13053
+ "switch",
13054
+ "light"
13055
+ ];
13056
+ var NUMERIC_AGGREGATES = [
13057
+ "mean",
13058
+ "median",
13059
+ "min",
13060
+ "max",
13061
+ "sum"
13062
+ ];
13063
+ var BINARY_AGGREGATES = ["any", "all"];
13064
+ /** How an actuator group decides it is on. Unknown members never count as off. */
13065
+ var ACTIVE_CRITERIA = ["at-least-one", "all"];
13066
+ var AGGREGATE_REDUCERS = [
13067
+ "mean",
13068
+ "median",
13069
+ "min",
13070
+ "max",
13071
+ "sum",
13072
+ "any",
13073
+ "all"
13074
+ ];
13075
+ var GroupTemplateIdSchema = _enum(GROUP_TEMPLATE_IDS);
13076
+ var AggregateReducerSchema = _enum(AGGREGATE_REDUCERS);
13077
+ var ActiveCriterionSchema = _enum(ACTIVE_CRITERIA);
13078
+ /** One member. The field is stored so occupancy can name motion or binary. */
13079
+ var HelperMemberSchema = object({
13080
+ source: CompositionSourceRefSchema,
13081
+ cap: string().min(1),
13082
+ fieldPath: string().min(1)
13083
+ });
13084
+ var HelperSpecSchema = discriminatedUnion("kind", [object({
13085
+ kind: literal("group"),
13086
+ templateId: GroupTemplateIdSchema,
13087
+ aggregate: AggregateReducerSchema,
13088
+ members: array(HelperMemberSchema).min(1).max(64),
13089
+ /** Actuator groups only. Readings leave this unset. */
13090
+ active: ActiveCriterionSchema.optional()
13091
+ })]);
13092
+ /** A composed device's stableId is this prefix plus the block id. */
13093
+ var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
13094
+ /** Longest snippet a `code` source may carry (slice 4). */
13095
+ var MAX_COMPOSITION_CODE_LENGTH = 2e4;
12966
13096
  /** One field of one capability of one source device. */
12967
13097
  var CompositionFieldReadSchema = object({
12968
13098
  source: CompositionSourceRefSchema,
@@ -13006,7 +13136,33 @@ var CompositionCodeSourceSchema = object({
13006
13136
  var CompositionFieldSourceSchema = discriminatedUnion("kind", [
13007
13137
  CompositionFromSourceSchema,
13008
13138
  CompositionExpressionSourceSchema,
13009
- CompositionCodeSourceSchema
13139
+ CompositionCodeSourceSchema,
13140
+ object({
13141
+ kind: literal("aggregate"),
13142
+ reducer: _enum([
13143
+ "mean",
13144
+ "median",
13145
+ "min",
13146
+ "max",
13147
+ "sum",
13148
+ "any",
13149
+ "all"
13150
+ ]),
13151
+ reads: array(CompositionFieldReadSchema).min(1).max(64),
13152
+ /** `value` is the reading; the others are the member counts. */
13153
+ publish: _enum([
13154
+ "value",
13155
+ "included",
13156
+ "excluded",
13157
+ "total"
13158
+ ]),
13159
+ /** What a `value` publish does when nobody is included. Counts ignore this. */
13160
+ empty: _enum([
13161
+ "null",
13162
+ "omit",
13163
+ "offline"
13164
+ ])
13165
+ })
13010
13166
  ]);
13011
13167
  var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
13012
13168
  kind: literal("forward"),
@@ -13052,7 +13208,13 @@ var CompositionSchema = object({
13052
13208
  kind: literal("existing"),
13053
13209
  device: CompositionSourceRefSchema
13054
13210
  })]),
13055
- features: array(CompositionFeatureSchema).min(1).max(16)
13211
+ features: array(CompositionFeatureSchema).min(1).max(16),
13212
+ /**
13213
+ * Present when the block is a helper template. Absent on a free
13214
+ * composition (the room example, device 4603). The editor reads this,
13215
+ * never the compiled features.
13216
+ */
13217
+ helper: HelperSpecSchema.optional()
13056
13218
  }).superRefine((composition, ctx) => {
13057
13219
  const seen = /* @__PURE__ */ new Set();
13058
13220
  composition.features.forEach((feature, index) => {
@@ -20983,7 +21145,10 @@ var CompositionProblemSchema = object({
20983
21145
  "target-missing",
20984
21146
  "target-unreadable",
20985
21147
  "not-replaceable",
20986
- "native-capability-replace"
21148
+ "native-capability-replace",
21149
+ "mixed-quantity",
21150
+ "helper-mismatch",
21151
+ "member-constraint"
20987
21152
  ]),
20988
21153
  path: string(),
20989
21154
  message: string()
@@ -21004,7 +21169,8 @@ var CompositionUnavailableModeSchema = _enum([
21004
21169
  "null",
21005
21170
  "offline",
21006
21171
  "unknown",
21007
- "release"
21172
+ "release",
21173
+ "omit"
21008
21174
  ]);
21009
21175
  /**
21010
21176
  * `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
@@ -21218,6 +21384,275 @@ Object.freeze({
21218
21384
  result: ["number", "null"]
21219
21385
  }
21220
21386
  });
21387
+ /**
21388
+ * One catalog row per base reading a group helper can build (D944 §3).
21389
+ * Data, not a form default written into the block.
21390
+ */
21391
+ var NOW = {
21392
+ fieldPath: "lastFetchedAt",
21393
+ expr: "now"
21394
+ };
21395
+ var CHANGED = {
21396
+ fieldPath: "lastChangedAt",
21397
+ expr: "now"
21398
+ };
21399
+ function numeric(input) {
21400
+ return {
21401
+ ...input,
21402
+ family: "numeric",
21403
+ deviceType: DeviceType.Sensor,
21404
+ memberDeviceType: DeviceType.Sensor,
21405
+ commandCaps: [],
21406
+ baseUnit: baseUnitOf(input.quantity),
21407
+ aggregates: NUMERIC_AGGREGATES,
21408
+ accept: [{
21409
+ cap: input.outputCap,
21410
+ fieldPath: input.outputField
21411
+ }]
21412
+ };
21413
+ }
21414
+ function binary(input) {
21415
+ return {
21416
+ ...input,
21417
+ family: "binary",
21418
+ deviceType: DeviceType.Sensor,
21419
+ memberDeviceType: DeviceType.Sensor,
21420
+ commandCaps: [],
21421
+ quantity: "none",
21422
+ baseUnit: void 0,
21423
+ aggregates: BINARY_AGGREGATES,
21424
+ empty: "offline"
21425
+ };
21426
+ }
21427
+ var GROUP_TEMPLATES = [
21428
+ numeric({
21429
+ id: "temperature",
21430
+ summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
21431
+ role: DeviceRole.TemperatureSensor,
21432
+ outputCap: "temperature-sensor",
21433
+ outputField: "celsius",
21434
+ quantity: "temperature",
21435
+ defaultAggregate: "mean",
21436
+ empty: "null",
21437
+ companions: [NOW]
21438
+ }),
21439
+ numeric({
21440
+ id: "humidity",
21441
+ summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
21442
+ role: DeviceRole.HumiditySensor,
21443
+ outputCap: "humidity-sensor",
21444
+ outputField: "percent",
21445
+ quantity: "humidity",
21446
+ defaultAggregate: "mean",
21447
+ empty: "null",
21448
+ companions: [NOW]
21449
+ }),
21450
+ numeric({
21451
+ id: "pressure",
21452
+ summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
21453
+ role: DeviceRole.PressureSensor,
21454
+ outputCap: "pressure-sensor",
21455
+ outputField: "hpa",
21456
+ quantity: "pressure",
21457
+ defaultAggregate: "mean",
21458
+ empty: "null",
21459
+ companions: [NOW]
21460
+ }),
21461
+ numeric({
21462
+ id: "illuminance",
21463
+ summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
21464
+ role: DeviceRole.AmbientLightSensor,
21465
+ outputCap: "ambient-light-sensor",
21466
+ outputField: "lux",
21467
+ quantity: "illuminance",
21468
+ defaultAggregate: "mean",
21469
+ empty: "null",
21470
+ companions: [NOW]
21471
+ }),
21472
+ numeric({
21473
+ id: "power",
21474
+ summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
21475
+ role: DeviceRole.PowerSensor,
21476
+ outputCap: "power-meter",
21477
+ outputField: "watts",
21478
+ quantity: "power",
21479
+ defaultAggregate: "sum",
21480
+ empty: "omit",
21481
+ companions: [NOW]
21482
+ }),
21483
+ numeric({
21484
+ id: "energy",
21485
+ summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
21486
+ role: DeviceRole.EnergySensor,
21487
+ outputCap: "power-meter",
21488
+ outputField: "kwhTotal",
21489
+ quantity: "energy",
21490
+ defaultAggregate: "sum",
21491
+ empty: "omit",
21492
+ companions: [NOW]
21493
+ }),
21494
+ numeric({
21495
+ id: "battery",
21496
+ summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
21497
+ role: DeviceRole.BatterySensor,
21498
+ outputCap: "battery",
21499
+ outputField: "percentage",
21500
+ quantity: "percentage",
21501
+ defaultAggregate: "mean",
21502
+ empty: "null",
21503
+ companions: [
21504
+ {
21505
+ fieldPath: "charging",
21506
+ expr: "\"unknown\""
21507
+ },
21508
+ {
21509
+ fieldPath: "sleeping",
21510
+ expr: "false"
21511
+ },
21512
+ {
21513
+ fieldPath: "lastUpdated",
21514
+ expr: "now"
21515
+ }
21516
+ ]
21517
+ }),
21518
+ numeric({
21519
+ id: "numeric",
21520
+ summary: "A numeric reading in the members’ shared quantity. Mixed quantities are refused. Nobody reporting publishes null, not 0.",
21521
+ role: DeviceRole.NumericSensor,
21522
+ outputCap: "numeric-sensor",
21523
+ outputField: "value",
21524
+ quantity: "device",
21525
+ defaultAggregate: "mean",
21526
+ empty: "null",
21527
+ companions: [NOW]
21528
+ }),
21529
+ binary({
21530
+ id: "motion",
21531
+ summary: "Any or all motion. Offline and unknown members are left out, never read as off. Nobody reporting takes the device offline.",
21532
+ role: DeviceRole.MotionSensor,
21533
+ outputCap: "motion",
21534
+ outputField: "detected",
21535
+ defaultAggregate: "any",
21536
+ accept: [{
21537
+ cap: "motion",
21538
+ fieldPath: "detected"
21539
+ }],
21540
+ companions: [{
21541
+ fieldPath: "lastDetectedAt",
21542
+ expr: "null"
21543
+ }, {
21544
+ fieldPath: "autoClearAfterMs",
21545
+ expr: "null"
21546
+ }]
21547
+ }),
21548
+ binary({
21549
+ id: "contact",
21550
+ summary: "Any or all open contacts. Offline and unknown members are left out, never read as closed.",
21551
+ role: DeviceRole.ContactSensor,
21552
+ outputCap: "contact",
21553
+ outputField: "entryOpen",
21554
+ defaultAggregate: "any",
21555
+ accept: [{
21556
+ cap: "contact",
21557
+ fieldPath: "entryOpen"
21558
+ }],
21559
+ companions: [CHANGED]
21560
+ }),
21561
+ binary({
21562
+ id: "leak",
21563
+ summary: "Any or all leak detections. Offline and unknown members are left out, never read as dry.",
21564
+ role: DeviceRole.LeakSensor,
21565
+ outputCap: "flood",
21566
+ outputField: "flooded",
21567
+ defaultAggregate: "any",
21568
+ accept: [{
21569
+ cap: "flood",
21570
+ fieldPath: "flooded"
21571
+ }],
21572
+ companions: [CHANGED]
21573
+ }),
21574
+ binary({
21575
+ id: "smoke",
21576
+ summary: "Any or all smoke detections. Offline and unknown members are left out, never read as clear.",
21577
+ role: DeviceRole.SmokeSensor,
21578
+ outputCap: "smoke",
21579
+ outputField: "detected",
21580
+ defaultAggregate: "any",
21581
+ accept: [{
21582
+ cap: "smoke",
21583
+ fieldPath: "detected"
21584
+ }],
21585
+ companions: [CHANGED]
21586
+ }),
21587
+ binary({
21588
+ id: "occupancy",
21589
+ summary: "Any or all of motion or binary sensors, published as a binary. Presence zones are not aggregated. Nobody reporting is offline, not off.",
21590
+ role: DeviceRole.BinarySensor,
21591
+ outputCap: "binary",
21592
+ outputField: "on",
21593
+ defaultAggregate: "any",
21594
+ accept: [{
21595
+ cap: "motion",
21596
+ fieldPath: "detected"
21597
+ }, {
21598
+ cap: "binary",
21599
+ fieldPath: "on"
21600
+ }],
21601
+ companions: [CHANGED]
21602
+ }),
21603
+ binary({
21604
+ id: "binary",
21605
+ summary: "Any or all generic binary sensors. Offline and unknown members are left out, never read as off.",
21606
+ role: DeviceRole.BinarySensor,
21607
+ outputCap: "binary",
21608
+ outputField: "on",
21609
+ defaultAggregate: "any",
21610
+ accept: [{
21611
+ cap: "binary",
21612
+ fieldPath: "on"
21613
+ }],
21614
+ companions: [CHANGED]
21615
+ }),
21616
+ actuator({
21617
+ id: "switch",
21618
+ summary: "On when at least one switch is on, or when all of them are. Offline and unknown members are left out of that decision, never read as off, and still receive the command.",
21619
+ deviceType: DeviceType.Switch,
21620
+ outputCap: "switch",
21621
+ commandCaps: ["switch"]
21622
+ }),
21623
+ actuator({
21624
+ id: "light",
21625
+ summary: "On when at least one light is on, or when all of them are. Brightness and colour are offered only when every member has them. A command is not sent to a member that lacks it.",
21626
+ deviceType: DeviceType.Light,
21627
+ outputCap: "switch",
21628
+ commandCaps: [
21629
+ "switch",
21630
+ "brightness",
21631
+ "color"
21632
+ ]
21633
+ })
21634
+ ];
21635
+ function actuator(input) {
21636
+ return {
21637
+ ...input,
21638
+ family: "actuator",
21639
+ role: void 0,
21640
+ memberDeviceType: input.deviceType,
21641
+ outputField: "on",
21642
+ quantity: "none",
21643
+ baseUnit: void 0,
21644
+ aggregates: BINARY_AGGREGATES,
21645
+ defaultAggregate: "any",
21646
+ empty: "offline",
21647
+ accept: [{
21648
+ cap: "switch",
21649
+ fieldPath: "on"
21650
+ }],
21651
+ companions: [CHANGED]
21652
+ };
21653
+ }
21654
+ new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
21655
+ DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
21221
21656
  `${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
21222
21657
  /**
21223
21658
  * What a composition may BUILD on a device type (G2, D676): the caps a new
@@ -48229,6 +48664,8 @@ var NcSystemEventKindSchema = _enum([
48229
48664
  "detection-blind",
48230
48665
  "motion-noisy",
48231
48666
  "motion-calm",
48667
+ "package-llm-silent",
48668
+ "package-llm-answered",
48232
48669
  "recording-stalled",
48233
48670
  "recording-healthy",
48234
48671
  "recording-degraded",
@@ -60083,6 +60520,28 @@ var PackageVersionInfoSchema = object({
60083
60520
  deprecated: string().optional(),
60084
60521
  distTags: array(string()).readonly()
60085
60522
  });
60523
+ /**
60524
+ * One published document. `ok` is markdown from the registry. `missing` means
60525
+ * the registry answered and the file was not there. `error` is a registry or
60526
+ * tarball failure — never an empty string standing in for either.
60527
+ */
60528
+ var PackageDocBodySchema = discriminatedUnion("status", [
60529
+ object({
60530
+ status: literal("ok"),
60531
+ markdown: string()
60532
+ }),
60533
+ object({ status: literal("missing") }),
60534
+ object({
60535
+ status: literal("error"),
60536
+ message: string()
60537
+ })
60538
+ ]);
60539
+ var PackageDocsSchema = object({
60540
+ name: string(),
60541
+ version: string(),
60542
+ readme: PackageDocBodySchema,
60543
+ changelog: PackageDocBodySchema
60544
+ });
60086
60545
  var SearchResultSchema = object({
60087
60546
  name: string(),
60088
60547
  version: string(),
@@ -60301,7 +60760,10 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
60301
60760
  }), object({ success: literal(true) }), {
60302
60761
  kind: "mutation",
60303
60762
  auth: "admin"
60304
- }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
60763
+ }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
60764
+ name: string().min(1),
60765
+ version: string().min(1).optional()
60766
+ }), PackageDocsSchema, { auth: "admin" }), method(object({ addonId: string() }), RestartAddonResultSchema, {
60305
60767
  kind: "mutation",
60306
60768
  auth: "admin"
60307
60769
  }), method(object({ packageName: string() }), object({ success: literal(true) }), {
@@ -62467,6 +62929,36 @@ object({
62467
62929
  lastChangedAt: number()
62468
62930
  });
62469
62931
  DeviceType.Sensor;
62932
+ object({
62933
+ /** One row per member that has been commanded. A later command replaces that member's row. */
62934
+ results: array(object({
62935
+ deviceId: number().int().nonnegative(),
62936
+ cap: string().min(1),
62937
+ method: string().min(1),
62938
+ ok: boolean(),
62939
+ error: string().optional(),
62940
+ /** Ms epoch of the attempt. */
62941
+ at: number()
62942
+ })) });
62943
+ DeviceType.Switch, DeviceType.Light;
62944
+ object({
62945
+ /** Members whose current value entered the aggregate. */
62946
+ included: number().int().nonnegative().meta(readingMeta("count", {
62947
+ precision: 0,
62948
+ label: "Reporting"
62949
+ })),
62950
+ /** Members left out: offline, unknown, or not a finite reading (D393). */
62951
+ excluded: number().int().nonnegative().meta(readingMeta("count", {
62952
+ precision: 0,
62953
+ label: "Excluded"
62954
+ })),
62955
+ /** `included` + `excluded`. */
62956
+ total: number().int().nonnegative().meta(readingMeta("count", {
62957
+ precision: 0,
62958
+ label: "Members"
62959
+ }))
62960
+ });
62961
+ DeviceType.Sensor, DeviceType.Switch, DeviceType.Light;
62470
62962
  object({
62471
62963
  /** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
62472
62964
  position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
@@ -70220,6 +70712,13 @@ Object.freeze({
70220
70712
  access: "view",
70221
70713
  role: "admin"
70222
70714
  },
70715
+ "addons.getPackageDocs": {
70716
+ capName: "addons",
70717
+ capScope: "system",
70718
+ addonId: null,
70719
+ access: "view",
70720
+ role: "admin"
70721
+ },
70223
70722
  "addons.getVersions": {
70224
70723
  capName: "addons",
70225
70724
  capScope: "system",
@@ -73328,6 +73827,20 @@ Object.freeze({
73328
73827
  access: "view",
73329
73828
  role: "viewer"
73330
73829
  },
73830
+ "groupCommands.getStatus": {
73831
+ capName: "group-commands",
73832
+ capScope: "device",
73833
+ addonId: null,
73834
+ access: "view",
73835
+ role: "viewer"
73836
+ },
73837
+ "groupStatus.getStatus": {
73838
+ capName: "group-status",
73839
+ capScope: "device",
73840
+ addonId: null,
73841
+ access: "view",
73842
+ role: "viewer"
73843
+ },
73331
73844
  "heatingValve.getStatus": {
73332
73845
  capName: "heating-valve",
73333
73846
  capScope: "device",
@@ -83150,6 +83663,37 @@ var SENSOR_CAP_VOCABULARY = {
83150
83663
  icon: "flame"
83151
83664
  }]
83152
83665
  },
83666
+ "group-commands": {
83667
+ scope: "device",
83668
+ noun: t("Group command", "Comando di gruppo")
83669
+ },
83670
+ "group-status": {
83671
+ scope: "device",
83672
+ noun: t("Group", "Gruppo"),
83673
+ state: [
83674
+ {
83675
+ kind: "numeric",
83676
+ field: "included",
83677
+ quantity: t("the members reporting", "i membri che rispondono"),
83678
+ label: t("Reporting", "Rispondono"),
83679
+ icon: "users"
83680
+ },
83681
+ {
83682
+ kind: "numeric",
83683
+ field: "excluded",
83684
+ quantity: t("the members left out", "i membri esclusi"),
83685
+ label: t("Excluded", "Esclusi"),
83686
+ icon: "users"
83687
+ },
83688
+ {
83689
+ kind: "numeric",
83690
+ field: "total",
83691
+ quantity: t("the member count", "il numero di membri"),
83692
+ label: t("Members", "Membri"),
83693
+ icon: "sigma"
83694
+ }
83695
+ ]
83696
+ },
83153
83697
  "humidity-sensor": {
83154
83698
  scope: "device",
83155
83699
  noun: t("Humidity", "Umidità"),
@@ -84615,6 +85159,16 @@ Object.freeze({
84615
85159
  form: "single",
84616
85160
  optional: false
84617
85161
  }],
85162
+ "groupCommands.getStatus": [{
85163
+ name: "deviceId",
85164
+ form: "single",
85165
+ optional: false
85166
+ }],
85167
+ "groupStatus.getStatus": [{
85168
+ name: "deviceId",
85169
+ form: "single",
85170
+ optional: false
85171
+ }],
84618
85172
  "heatingValve.getStatus": [{
84619
85173
  name: "deviceId",
84620
85174
  form: "single",
@@ -86649,6 +87203,8 @@ new Map(Object.entries({
86649
87203
  "detection-blind": "device-events",
86650
87204
  "motion-noisy": "device-events",
86651
87205
  "motion-calm": "device-events",
87206
+ "package-llm-silent": "device-events",
87207
+ "package-llm-answered": "device-events",
86652
87208
  "recording-stalled": "device-events",
86653
87209
  "recording-healthy": "device-events",
86654
87210
  "recording-degraded": "device-events",
@@ -86732,6 +87288,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
86732
87288
  label: "Motion without a subject",
86733
87289
  kinds: ["motion-noisy", "motion-calm"]
86734
87290
  },
87291
+ {
87292
+ id: "package-llm",
87293
+ family: "device-events",
87294
+ label: "Package confirm",
87295
+ kinds: ["package-llm-silent", "package-llm-answered"]
87296
+ },
86735
87297
  {
86736
87298
  id: "recording",
86737
87299
  family: "device-events",
@@ -86913,6 +87475,8 @@ var DEVICE_EVENTS = [
86913
87475
  "detection-blind",
86914
87476
  "motion-noisy",
86915
87477
  "motion-calm",
87478
+ "package-llm-silent",
87479
+ "package-llm-answered",
86916
87480
  "recording-stalled",
86917
87481
  "recording-healthy",
86918
87482
  "recording-degraded",
@@ -87181,6 +87745,15 @@ new Map([
87181
87745
  snapshotLabel: "Cameras with constant motion now",
87182
87746
  snapshotSection: null
87183
87747
  },
87748
+ {
87749
+ id: "package-llm-confirm",
87750
+ family: "device-events",
87751
+ label: "Package confirm (not answering / answering again)",
87752
+ bad: ["package-llm-silent"],
87753
+ recovery: ["package-llm-answered"],
87754
+ snapshotLabel: "Cameras whose package confirm is not answering",
87755
+ snapshotSection: null
87756
+ },
87184
87757
  {
87185
87758
  id: "recording-health",
87186
87759
  family: "device-events",