@camstack/addon-post-analysis 1.2.637 → 1.2.639

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 (17) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +22 -0
  3. package/dist/{clip-model-registry-DF_J6DGP.mjs → clip-model-registry-B-Dv5y3Z.mjs} +669 -22
  4. package/dist/{clip-model-registry-GzUKh4GO.js → clip-model-registry-DEcrrqRz.js} +669 -22
  5. package/dist/embedding-encoder/index.js +1 -1
  6. package/dist/embedding-encoder/index.mjs +1 -1
  7. package/dist/pipeline-analytics/_stub.js +2 -2
  8. package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-CD4U2vp3.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-DRZLmZDb.mjs} +2 -2
  9. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-D4TYbuPV.mjs +26 -0
  10. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-Cc4lAtK3.mjs +26 -0
  11. package/dist/pipeline-analytics/{hostInit-Bdn1ny7s.mjs → hostInit-B07ueo2X.mjs} +2 -2
  12. package/dist/pipeline-analytics/index.js +370 -105
  13. package/dist/pipeline-analytics/index.mjs +370 -105
  14. package/dist/pipeline-analytics/remoteEntry.js +1 -1
  15. package/package.json +4 -2
  16. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CLg3GhZM.mjs +0 -26
  17. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-Bcrs7B9G.mjs +0 -26
@@ -30,7 +30,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
30
  }) : target, mod));
31
31
  //#endregion
32
32
  let node_crypto = require("node:crypto");
33
- //#region ../types/dist/event-category-DHXxB8t9.mjs
33
+ //#region ../types/dist/event-category-CT-hz5Rb.mjs
34
34
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
35
35
  EventCategory["SystemBoot"] = "system.boot";
36
36
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -356,6 +356,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
356
356
  /** The recovery edge of {@link PipelineMotionNoisy}: the motion fell back, or a detection arrived. */
357
357
  EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
358
358
  /**
359
+ * A camera's package LLM confirm has failed closed three times in a row
360
+ * (D931, 2026-10-26). One edge per camera until
361
+ * {@link PipelinePackageLlmAnswered}.
362
+ */
363
+ EventCategory["PipelinePackageLlmSilent"] = "pipeline.package-llm-silent";
364
+ /** The recovery edge of {@link PipelinePackageLlmSilent}: a confirm returned yes or no. */
365
+ EventCategory["PipelinePackageLlmAnswered"] = "pipeline.package-llm-answered";
366
+ /**
359
367
  * Per-camera pipeline config was mutated by the orchestrator
360
368
  * (a settings change via `setAgentInferenceDevices` /
361
369
  * `setCameraStepToggle` / `setCameraStepSettings`). Orchestrator
@@ -5663,7 +5671,7 @@ var ZodIssueCode = {
5663
5671
  var ZodFirstPartyTypeKind;
5664
5672
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5665
5673
  //#endregion
5666
- //#region ../types/dist/sleep-CARd6wZF.mjs
5674
+ //#region ../types/dist/sleep-bykKrTgu.mjs
5667
5675
  /**
5668
5676
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5669
5677
  * window to float samples (D455).
@@ -8402,6 +8410,53 @@ var READING_QUANTITIES = [
8402
8410
  ];
8403
8411
  var ReadingQuantitySchema = _enum(READING_QUANTITIES);
8404
8412
  new Set(READING_QUANTITIES);
8413
+ /**
8414
+ * Stored unit symbol for a quantity. `none` means the number is dimensionless
8415
+ * (or an index / ratio / count). `device` means the cap has no single unit.
8416
+ */
8417
+ var QUANTITY_BASE = {
8418
+ temperature: "°C",
8419
+ pressure: "hPa",
8420
+ speed: "m/s",
8421
+ precipitation: "mm",
8422
+ "precipitation-rate": "mm/h",
8423
+ length: "m",
8424
+ area: "m²",
8425
+ illuminance: "lx",
8426
+ irradiance: "W/m²",
8427
+ power: "W",
8428
+ energy: "kWh",
8429
+ voltage: "V",
8430
+ current: "A",
8431
+ "apparent-power": "VA",
8432
+ humidity: "%",
8433
+ percentage: "%",
8434
+ "concentration-volume": "ppm",
8435
+ "concentration-mass": "µg/m³",
8436
+ "concentration-ppb": "ppb",
8437
+ volume: "L",
8438
+ duration: "s",
8439
+ "duration-ms": "ms",
8440
+ information: "B",
8441
+ "sound-level": "dBFS",
8442
+ "signal-level": "dBm",
8443
+ "colour-temperature": "mired",
8444
+ angle: "°",
8445
+ bitrate: "kbps",
8446
+ rate: "fps",
8447
+ mass: "kg",
8448
+ index: "none",
8449
+ ratio: "none",
8450
+ count: "none",
8451
+ none: "none",
8452
+ device: "device"
8453
+ };
8454
+ /** The stored unit, or `undefined` when the quantity has no unit symbol. */
8455
+ function baseUnitOf(quantity) {
8456
+ const symbol = QUANTITY_BASE[quantity];
8457
+ if (symbol === "none" || symbol === "device") return void 0;
8458
+ return symbol;
8459
+ }
8405
8460
  function readingMeta(quantity, extras) {
8406
8461
  return {
8407
8462
  quantity,
@@ -9037,6 +9092,8 @@ var CAP_NAMES = Object.freeze([
9037
9092
  "filesystem-browse",
9038
9093
  "flood",
9039
9094
  "gas",
9095
+ "group-commands",
9096
+ "group-status",
9040
9097
  "heating-valve",
9041
9098
  "humidifier",
9042
9099
  "humidity-sensor",
@@ -9855,6 +9912,20 @@ Object.freeze({
9855
9912
  "path": "detected",
9856
9913
  "valueType": "boolean"
9857
9914
  }],
9915
+ "group-status": [
9916
+ {
9917
+ "path": "included",
9918
+ "valueType": "number"
9919
+ },
9920
+ {
9921
+ "path": "excluded",
9922
+ "valueType": "number"
9923
+ },
9924
+ {
9925
+ "path": "total",
9926
+ "valueType": "number"
9927
+ }
9928
+ ],
9858
9929
  "heating-valve": [{
9859
9930
  "path": "position",
9860
9931
  "valueType": "number"
@@ -10845,7 +10916,7 @@ Object.freeze({
10845
10916
  * can answer "may a rule actuate this?" without importing the schema barrel
10846
10917
  * (~144MB RSS per runner, D28).
10847
10918
  *
10848
- * Coverage: 91 device-scoped capabilities.
10919
+ * Coverage: 93 device-scoped capabilities.
10849
10920
  */
10850
10921
  var DEVICE_SCOPED_CAPS = new Set([
10851
10922
  "accessories",
@@ -10886,6 +10957,8 @@ var DEVICE_SCOPED_CAPS = new Set([
10886
10957
  "feature-probe",
10887
10958
  "flood",
10888
10959
  "gas",
10960
+ "group-commands",
10961
+ "group-status",
10889
10962
  "heating-valve",
10890
10963
  "humidifier",
10891
10964
  "humidity-sensor",
@@ -11337,7 +11410,7 @@ function errMsg(err) {
11337
11410
  return String(err);
11338
11411
  }
11339
11412
  //#endregion
11340
- //#region ../types/dist/composition-kEl9mevu.mjs
11413
+ //#region ../types/dist/composition-OhpuespA.mjs
11341
11414
  /**
11342
11415
  * Deterministic SHA-256 hash of an arbitrary serialisable value. The
11343
11416
  * canonical form sorts object keys alphabetically at every depth so two
@@ -12252,15 +12325,74 @@ function validateExpressionSource(src) {
12252
12325
  }
12253
12326
  return null;
12254
12327
  }
12255
- /** A composed device's stableId is this prefix plus the block id. */
12256
- var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
12257
- /** Longest snippet a `code` source may carry (slice 4). */
12258
- var MAX_COMPOSITION_CODE_LENGTH = 2e4;
12328
+ /**
12329
+ * A composition source identity: `(addonId, stableId)`, never a numeric device
12330
+ * id. Split out so helper schemas can name it without a cycle through
12331
+ * `composition.ts` (D659).
12332
+ */
12259
12333
  var CompositionSourceRefSchema = object({
12260
12334
  /** The owning addon; `stableId` is unique only within it. */
12261
12335
  addonId: string().min(1),
12262
12336
  stableId: string().min(1)
12263
12337
  });
12338
+ var GROUP_TEMPLATE_IDS = [
12339
+ "temperature",
12340
+ "humidity",
12341
+ "pressure",
12342
+ "illuminance",
12343
+ "power",
12344
+ "energy",
12345
+ "battery",
12346
+ "numeric",
12347
+ "motion",
12348
+ "contact",
12349
+ "leak",
12350
+ "smoke",
12351
+ "occupancy",
12352
+ "binary",
12353
+ "switch",
12354
+ "light"
12355
+ ];
12356
+ var NUMERIC_AGGREGATES = [
12357
+ "mean",
12358
+ "median",
12359
+ "min",
12360
+ "max",
12361
+ "sum"
12362
+ ];
12363
+ var BINARY_AGGREGATES = ["any", "all"];
12364
+ /** How an actuator group decides it is on. Unknown members never count as off. */
12365
+ var ACTIVE_CRITERIA = ["at-least-one", "all"];
12366
+ var AGGREGATE_REDUCERS = [
12367
+ "mean",
12368
+ "median",
12369
+ "min",
12370
+ "max",
12371
+ "sum",
12372
+ "any",
12373
+ "all"
12374
+ ];
12375
+ var GroupTemplateIdSchema = _enum(GROUP_TEMPLATE_IDS);
12376
+ var AggregateReducerSchema = _enum(AGGREGATE_REDUCERS);
12377
+ var ActiveCriterionSchema = _enum(ACTIVE_CRITERIA);
12378
+ /** One member. The field is stored so occupancy can name motion or binary. */
12379
+ var HelperMemberSchema = object({
12380
+ source: CompositionSourceRefSchema,
12381
+ cap: string().min(1),
12382
+ fieldPath: string().min(1)
12383
+ });
12384
+ var HelperSpecSchema = discriminatedUnion("kind", [object({
12385
+ kind: literal("group"),
12386
+ templateId: GroupTemplateIdSchema,
12387
+ aggregate: AggregateReducerSchema,
12388
+ members: array(HelperMemberSchema).min(1).max(64),
12389
+ /** Actuator groups only. Readings leave this unset. */
12390
+ active: ActiveCriterionSchema.optional()
12391
+ })]);
12392
+ /** A composed device's stableId is this prefix plus the block id. */
12393
+ var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
12394
+ /** Longest snippet a `code` source may carry (slice 4). */
12395
+ var MAX_COMPOSITION_CODE_LENGTH = 2e4;
12264
12396
  /** One field of one capability of one source device. */
12265
12397
  var CompositionFieldReadSchema = object({
12266
12398
  source: CompositionSourceRefSchema,
@@ -12304,7 +12436,33 @@ var CompositionCodeSourceSchema = object({
12304
12436
  var CompositionFieldSourceSchema = discriminatedUnion("kind", [
12305
12437
  CompositionFromSourceSchema,
12306
12438
  CompositionExpressionSourceSchema,
12307
- CompositionCodeSourceSchema
12439
+ CompositionCodeSourceSchema,
12440
+ object({
12441
+ kind: literal("aggregate"),
12442
+ reducer: _enum([
12443
+ "mean",
12444
+ "median",
12445
+ "min",
12446
+ "max",
12447
+ "sum",
12448
+ "any",
12449
+ "all"
12450
+ ]),
12451
+ reads: array(CompositionFieldReadSchema).min(1).max(64),
12452
+ /** `value` is the reading; the others are the member counts. */
12453
+ publish: _enum([
12454
+ "value",
12455
+ "included",
12456
+ "excluded",
12457
+ "total"
12458
+ ]),
12459
+ /** What a `value` publish does when nobody is included. Counts ignore this. */
12460
+ empty: _enum([
12461
+ "null",
12462
+ "omit",
12463
+ "offline"
12464
+ ])
12465
+ })
12308
12466
  ]);
12309
12467
  var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
12310
12468
  kind: literal("forward"),
@@ -12350,7 +12508,13 @@ var CompositionSchema = object({
12350
12508
  kind: literal("existing"),
12351
12509
  device: CompositionSourceRefSchema
12352
12510
  })]),
12353
- features: array(CompositionFeatureSchema).min(1).max(16)
12511
+ features: array(CompositionFeatureSchema).min(1).max(16),
12512
+ /**
12513
+ * Present when the block is a helper template. Absent on a free
12514
+ * composition (the room example, device 4603). The editor reads this,
12515
+ * never the compiled features.
12516
+ */
12517
+ helper: HelperSpecSchema.optional()
12354
12518
  }).superRefine((composition, ctx) => {
12355
12519
  const seen = /* @__PURE__ */ new Set();
12356
12520
  composition.features.forEach((feature, index) => {
@@ -19342,7 +19506,10 @@ var CompositionProblemSchema = object({
19342
19506
  "target-missing",
19343
19507
  "target-unreadable",
19344
19508
  "not-replaceable",
19345
- "native-capability-replace"
19509
+ "native-capability-replace",
19510
+ "mixed-quantity",
19511
+ "helper-mismatch",
19512
+ "member-constraint"
19346
19513
  ]),
19347
19514
  path: string(),
19348
19515
  message: string()
@@ -19363,7 +19530,8 @@ var CompositionUnavailableModeSchema = _enum([
19363
19530
  "null",
19364
19531
  "offline",
19365
19532
  "unknown",
19366
- "release"
19533
+ "release",
19534
+ "omit"
19367
19535
  ]);
19368
19536
  /**
19369
19537
  * `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
@@ -19577,6 +19745,275 @@ Object.freeze({
19577
19745
  result: ["number", "null"]
19578
19746
  }
19579
19747
  });
19748
+ /**
19749
+ * One catalog row per base reading a group helper can build (D944 §3).
19750
+ * Data, not a form default written into the block.
19751
+ */
19752
+ var NOW = {
19753
+ fieldPath: "lastFetchedAt",
19754
+ expr: "now"
19755
+ };
19756
+ var CHANGED = {
19757
+ fieldPath: "lastChangedAt",
19758
+ expr: "now"
19759
+ };
19760
+ function numeric(input) {
19761
+ return {
19762
+ ...input,
19763
+ family: "numeric",
19764
+ deviceType: DeviceType.Sensor,
19765
+ memberDeviceType: DeviceType.Sensor,
19766
+ commandCaps: [],
19767
+ baseUnit: baseUnitOf(input.quantity),
19768
+ aggregates: NUMERIC_AGGREGATES,
19769
+ accept: [{
19770
+ cap: input.outputCap,
19771
+ fieldPath: input.outputField
19772
+ }]
19773
+ };
19774
+ }
19775
+ function binary(input) {
19776
+ return {
19777
+ ...input,
19778
+ family: "binary",
19779
+ deviceType: DeviceType.Sensor,
19780
+ memberDeviceType: DeviceType.Sensor,
19781
+ commandCaps: [],
19782
+ quantity: "none",
19783
+ baseUnit: void 0,
19784
+ aggregates: BINARY_AGGREGATES,
19785
+ empty: "offline"
19786
+ };
19787
+ }
19788
+ var GROUP_TEMPLATES = [
19789
+ numeric({
19790
+ id: "temperature",
19791
+ summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
19792
+ role: DeviceRole.TemperatureSensor,
19793
+ outputCap: "temperature-sensor",
19794
+ outputField: "celsius",
19795
+ quantity: "temperature",
19796
+ defaultAggregate: "mean",
19797
+ empty: "null",
19798
+ companions: [NOW]
19799
+ }),
19800
+ numeric({
19801
+ id: "humidity",
19802
+ summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
19803
+ role: DeviceRole.HumiditySensor,
19804
+ outputCap: "humidity-sensor",
19805
+ outputField: "percent",
19806
+ quantity: "humidity",
19807
+ defaultAggregate: "mean",
19808
+ empty: "null",
19809
+ companions: [NOW]
19810
+ }),
19811
+ numeric({
19812
+ id: "pressure",
19813
+ summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
19814
+ role: DeviceRole.PressureSensor,
19815
+ outputCap: "pressure-sensor",
19816
+ outputField: "hpa",
19817
+ quantity: "pressure",
19818
+ defaultAggregate: "mean",
19819
+ empty: "null",
19820
+ companions: [NOW]
19821
+ }),
19822
+ numeric({
19823
+ id: "illuminance",
19824
+ summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
19825
+ role: DeviceRole.AmbientLightSensor,
19826
+ outputCap: "ambient-light-sensor",
19827
+ outputField: "lux",
19828
+ quantity: "illuminance",
19829
+ defaultAggregate: "mean",
19830
+ empty: "null",
19831
+ companions: [NOW]
19832
+ }),
19833
+ numeric({
19834
+ id: "power",
19835
+ summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
19836
+ role: DeviceRole.PowerSensor,
19837
+ outputCap: "power-meter",
19838
+ outputField: "watts",
19839
+ quantity: "power",
19840
+ defaultAggregate: "sum",
19841
+ empty: "omit",
19842
+ companions: [NOW]
19843
+ }),
19844
+ numeric({
19845
+ id: "energy",
19846
+ summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
19847
+ role: DeviceRole.EnergySensor,
19848
+ outputCap: "power-meter",
19849
+ outputField: "kwhTotal",
19850
+ quantity: "energy",
19851
+ defaultAggregate: "sum",
19852
+ empty: "omit",
19853
+ companions: [NOW]
19854
+ }),
19855
+ numeric({
19856
+ id: "battery",
19857
+ summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
19858
+ role: DeviceRole.BatterySensor,
19859
+ outputCap: "battery",
19860
+ outputField: "percentage",
19861
+ quantity: "percentage",
19862
+ defaultAggregate: "mean",
19863
+ empty: "null",
19864
+ companions: [
19865
+ {
19866
+ fieldPath: "charging",
19867
+ expr: "\"unknown\""
19868
+ },
19869
+ {
19870
+ fieldPath: "sleeping",
19871
+ expr: "false"
19872
+ },
19873
+ {
19874
+ fieldPath: "lastUpdated",
19875
+ expr: "now"
19876
+ }
19877
+ ]
19878
+ }),
19879
+ numeric({
19880
+ id: "numeric",
19881
+ summary: "A numeric reading in the members’ shared quantity. Mixed quantities are refused. Nobody reporting publishes null, not 0.",
19882
+ role: DeviceRole.NumericSensor,
19883
+ outputCap: "numeric-sensor",
19884
+ outputField: "value",
19885
+ quantity: "device",
19886
+ defaultAggregate: "mean",
19887
+ empty: "null",
19888
+ companions: [NOW]
19889
+ }),
19890
+ binary({
19891
+ id: "motion",
19892
+ summary: "Any or all motion. Offline and unknown members are left out, never read as off. Nobody reporting takes the device offline.",
19893
+ role: DeviceRole.MotionSensor,
19894
+ outputCap: "motion",
19895
+ outputField: "detected",
19896
+ defaultAggregate: "any",
19897
+ accept: [{
19898
+ cap: "motion",
19899
+ fieldPath: "detected"
19900
+ }],
19901
+ companions: [{
19902
+ fieldPath: "lastDetectedAt",
19903
+ expr: "null"
19904
+ }, {
19905
+ fieldPath: "autoClearAfterMs",
19906
+ expr: "null"
19907
+ }]
19908
+ }),
19909
+ binary({
19910
+ id: "contact",
19911
+ summary: "Any or all open contacts. Offline and unknown members are left out, never read as closed.",
19912
+ role: DeviceRole.ContactSensor,
19913
+ outputCap: "contact",
19914
+ outputField: "entryOpen",
19915
+ defaultAggregate: "any",
19916
+ accept: [{
19917
+ cap: "contact",
19918
+ fieldPath: "entryOpen"
19919
+ }],
19920
+ companions: [CHANGED]
19921
+ }),
19922
+ binary({
19923
+ id: "leak",
19924
+ summary: "Any or all leak detections. Offline and unknown members are left out, never read as dry.",
19925
+ role: DeviceRole.LeakSensor,
19926
+ outputCap: "flood",
19927
+ outputField: "flooded",
19928
+ defaultAggregate: "any",
19929
+ accept: [{
19930
+ cap: "flood",
19931
+ fieldPath: "flooded"
19932
+ }],
19933
+ companions: [CHANGED]
19934
+ }),
19935
+ binary({
19936
+ id: "smoke",
19937
+ summary: "Any or all smoke detections. Offline and unknown members are left out, never read as clear.",
19938
+ role: DeviceRole.SmokeSensor,
19939
+ outputCap: "smoke",
19940
+ outputField: "detected",
19941
+ defaultAggregate: "any",
19942
+ accept: [{
19943
+ cap: "smoke",
19944
+ fieldPath: "detected"
19945
+ }],
19946
+ companions: [CHANGED]
19947
+ }),
19948
+ binary({
19949
+ id: "occupancy",
19950
+ summary: "Any or all of motion or binary sensors, published as a binary. Presence zones are not aggregated. Nobody reporting is offline, not off.",
19951
+ role: DeviceRole.BinarySensor,
19952
+ outputCap: "binary",
19953
+ outputField: "on",
19954
+ defaultAggregate: "any",
19955
+ accept: [{
19956
+ cap: "motion",
19957
+ fieldPath: "detected"
19958
+ }, {
19959
+ cap: "binary",
19960
+ fieldPath: "on"
19961
+ }],
19962
+ companions: [CHANGED]
19963
+ }),
19964
+ binary({
19965
+ id: "binary",
19966
+ summary: "Any or all generic binary sensors. Offline and unknown members are left out, never read as off.",
19967
+ role: DeviceRole.BinarySensor,
19968
+ outputCap: "binary",
19969
+ outputField: "on",
19970
+ defaultAggregate: "any",
19971
+ accept: [{
19972
+ cap: "binary",
19973
+ fieldPath: "on"
19974
+ }],
19975
+ companions: [CHANGED]
19976
+ }),
19977
+ actuator({
19978
+ id: "switch",
19979
+ 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.",
19980
+ deviceType: DeviceType.Switch,
19981
+ outputCap: "switch",
19982
+ commandCaps: ["switch"]
19983
+ }),
19984
+ actuator({
19985
+ id: "light",
19986
+ 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.",
19987
+ deviceType: DeviceType.Light,
19988
+ outputCap: "switch",
19989
+ commandCaps: [
19990
+ "switch",
19991
+ "brightness",
19992
+ "color"
19993
+ ]
19994
+ })
19995
+ ];
19996
+ function actuator(input) {
19997
+ return {
19998
+ ...input,
19999
+ family: "actuator",
20000
+ role: void 0,
20001
+ memberDeviceType: input.deviceType,
20002
+ outputField: "on",
20003
+ quantity: "none",
20004
+ baseUnit: void 0,
20005
+ aggregates: BINARY_AGGREGATES,
20006
+ defaultAggregate: "any",
20007
+ empty: "offline",
20008
+ accept: [{
20009
+ cap: "switch",
20010
+ fieldPath: "on"
20011
+ }],
20012
+ companions: [CHANGED]
20013
+ };
20014
+ }
20015
+ new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
20016
+ DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
19580
20017
  `${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
19581
20018
  /**
19582
20019
  * What a composition may BUILD on a device type (G2, D676): the caps a new
@@ -46532,6 +46969,8 @@ var NcSystemEventKindSchema = _enum([
46532
46969
  "detection-blind",
46533
46970
  "motion-noisy",
46534
46971
  "motion-calm",
46972
+ "package-llm-silent",
46973
+ "package-llm-answered",
46535
46974
  "recording-stalled",
46536
46975
  "recording-healthy",
46537
46976
  "recording-degraded",
@@ -48094,6 +48533,14 @@ var NC_CONDITION_CATALOG = [
48094
48533
  value: "motion-calm",
48095
48534
  label: "Camera motion calm again"
48096
48535
  },
48536
+ {
48537
+ value: "package-llm-silent",
48538
+ label: "Package confirm not answering"
48539
+ },
48540
+ {
48541
+ value: "package-llm-answered",
48542
+ label: "Package confirm answering again"
48543
+ },
48097
48544
  {
48098
48545
  value: "recording-stalled",
48099
48546
  label: "Recording stalled"
@@ -59469,6 +59916,28 @@ var PackageVersionInfoSchema = object({
59469
59916
  deprecated: string().optional(),
59470
59917
  distTags: array(string()).readonly()
59471
59918
  });
59919
+ /**
59920
+ * One published document. `ok` is markdown from the registry. `missing` means
59921
+ * the registry answered and the file was not there. `error` is a registry or
59922
+ * tarball failure — never an empty string standing in for either.
59923
+ */
59924
+ var PackageDocBodySchema = discriminatedUnion("status", [
59925
+ object({
59926
+ status: literal("ok"),
59927
+ markdown: string()
59928
+ }),
59929
+ object({ status: literal("missing") }),
59930
+ object({
59931
+ status: literal("error"),
59932
+ message: string()
59933
+ })
59934
+ ]);
59935
+ var PackageDocsSchema = object({
59936
+ name: string(),
59937
+ version: string(),
59938
+ readme: PackageDocBodySchema,
59939
+ changelog: PackageDocBodySchema
59940
+ });
59472
59941
  var SearchResultSchema = object({
59473
59942
  name: string(),
59474
59943
  version: string(),
@@ -59687,7 +60156,10 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
59687
60156
  }), object({ success: literal(true) }), {
59688
60157
  kind: "mutation",
59689
60158
  auth: "admin"
59690
- }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
60159
+ }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
60160
+ name: string().min(1),
60161
+ version: string().min(1).optional()
60162
+ }), PackageDocsSchema, { auth: "admin" }), method(object({ addonId: string() }), RestartAddonResultSchema, {
59691
60163
  kind: "mutation",
59692
60164
  auth: "admin"
59693
60165
  }), method(object({ packageName: string() }), object({ success: literal(true) }), {
@@ -63109,6 +63581,88 @@ var gasCapability = {
63109
63581
  * whether persisting is worth a SQLite commit. */
63110
63582
  volatileStateFields: ["lastChangedAt"]
63111
63583
  };
63584
+ var GroupCommandsSchema = object({
63585
+ /** One row per member that has been commanded. A later command replaces that member's row. */
63586
+ results: array(object({
63587
+ deviceId: number().int().nonnegative(),
63588
+ cap: string().min(1),
63589
+ method: string().min(1),
63590
+ ok: boolean(),
63591
+ error: string().optional(),
63592
+ /** Ms epoch of the attempt. */
63593
+ at: number()
63594
+ })) });
63595
+ var groupCommandsCapability = {
63596
+ name: "group-commands",
63597
+ scope: "device",
63598
+ deviceNative: true,
63599
+ mode: "singleton",
63600
+ deviceTypes: [DeviceType.Switch, DeviceType.Light],
63601
+ methods: {},
63602
+ status: {
63603
+ schema: GroupCommandsSchema,
63604
+ kind: "push"
63605
+ },
63606
+ runtimeState: GroupCommandsSchema,
63607
+ /**
63608
+ * Runtime-state durability: **session** — the last attempt. A restored
63609
+ * failure would outlive the command that caused it.
63610
+ *
63611
+ * See `RuntimeStateDurability`. Enforced by
63612
+ * `scripts/check-runtime-state-durability.ts`.
63613
+ */
63614
+ durability: "session",
63615
+ history: "none"
63616
+ };
63617
+ /**
63618
+ * How many members of a helper group answered (D944). Counts are integers,
63619
+ * not measurements: zero included is a real count, never a stand-in reading.
63620
+ * The reading itself stays on the output capability. History is none — the
63621
+ * series that later statistics read is the output cap's own history block.
63622
+ */
63623
+ var GroupStatusSchema = object({
63624
+ /** Members whose current value entered the aggregate. */
63625
+ included: number().int().nonnegative().meta(readingMeta("count", {
63626
+ precision: 0,
63627
+ label: "Reporting"
63628
+ })),
63629
+ /** Members left out: offline, unknown, or not a finite reading (D393). */
63630
+ excluded: number().int().nonnegative().meta(readingMeta("count", {
63631
+ precision: 0,
63632
+ label: "Excluded"
63633
+ })),
63634
+ /** `included` + `excluded`. */
63635
+ total: number().int().nonnegative().meta(readingMeta("count", {
63636
+ precision: 0,
63637
+ label: "Members"
63638
+ }))
63639
+ });
63640
+ var groupStatusCapability = {
63641
+ name: "group-status",
63642
+ scope: "device",
63643
+ deviceNative: true,
63644
+ mode: "singleton",
63645
+ deviceTypes: [
63646
+ DeviceType.Sensor,
63647
+ DeviceType.Switch,
63648
+ DeviceType.Light
63649
+ ],
63650
+ methods: {},
63651
+ status: {
63652
+ schema: GroupStatusSchema,
63653
+ kind: "push"
63654
+ },
63655
+ runtimeState: GroupStatusSchema,
63656
+ /**
63657
+ * Runtime-state durability: **session** — recomputed from members on the
63658
+ * next source event; a restored count would outlive the readings it named.
63659
+ *
63660
+ * See `RuntimeStateDurability`. Enforced by
63661
+ * `scripts/check-runtime-state-durability.ts`.
63662
+ */
63663
+ durability: "session",
63664
+ history: "none"
63665
+ };
63112
63666
  var HeatingValveStatusSchema = object({
63113
63667
  /** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
63114
63668
  position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
@@ -64924,12 +65478,18 @@ var motionCapability = {
64924
65478
  methods: {
64925
65479
  /**
64926
65480
  * Pull the current motion state synchronously. Convenience shortcut
64927
- * for consumers that don't need the full status object; equivalent
64928
- * to `getStatus()?.detected ?? false`. Will likely be folded into
64929
- * `getStatus` once the auto-injected status surface lands in every
64930
- * consumer.
65481
+ * for consumers that don't need the full status object. A composed
65482
+ * group answers from its slice (D944): unknown throws, it is not off.
64931
65483
  */
64932
65484
  isDetected: method(object({ deviceId: number() }), boolean()) },
65485
+ /**
65486
+ * A composed motion group serves `isDetected` from `detected` (D944).
65487
+ * Without this the cap stays uncomposable (`has-commands`).
65488
+ */
65489
+ composedMethods: { isDetected: {
65490
+ kind: "slice",
65491
+ field: "detected"
65492
+ } },
64933
65493
  events: {
64934
65494
  /**
64935
65495
  * Fires every time the runner transitions a camera between
@@ -72875,6 +73435,8 @@ var DEVICE_LOCAL_STATE_CAPS = {
72875
73435
  featureProbe: featureProbeCapability,
72876
73436
  flood: floodCapability,
72877
73437
  gas: gasCapability,
73438
+ groupCommands: groupCommandsCapability,
73439
+ groupStatus: groupStatusCapability,
72878
73440
  heatingValve: heatingValveCapability,
72879
73441
  humidifier: humidifierCapability,
72880
73442
  humiditySensor: humiditySensorCapability,
@@ -73768,6 +74330,13 @@ Object.freeze({
73768
74330
  access: "view",
73769
74331
  role: "admin"
73770
74332
  },
74333
+ "addons.getPackageDocs": {
74334
+ capName: "addons",
74335
+ capScope: "system",
74336
+ addonId: null,
74337
+ access: "view",
74338
+ role: "admin"
74339
+ },
73771
74340
  "addons.getVersions": {
73772
74341
  capName: "addons",
73773
74342
  capScope: "system",
@@ -76876,6 +77445,20 @@ Object.freeze({
76876
77445
  access: "view",
76877
77446
  role: "viewer"
76878
77447
  },
77448
+ "groupCommands.getStatus": {
77449
+ capName: "group-commands",
77450
+ capScope: "device",
77451
+ addonId: null,
77452
+ access: "view",
77453
+ role: "viewer"
77454
+ },
77455
+ "groupStatus.getStatus": {
77456
+ capName: "group-status",
77457
+ capScope: "device",
77458
+ addonId: null,
77459
+ access: "view",
77460
+ role: "viewer"
77461
+ },
76879
77462
  "heatingValve.getStatus": {
76880
77463
  capName: "heating-valve",
76881
77464
  capScope: "device",
@@ -86698,6 +87281,37 @@ var SENSOR_CAP_VOCABULARY = {
86698
87281
  icon: "flame"
86699
87282
  }]
86700
87283
  },
87284
+ "group-commands": {
87285
+ scope: "device",
87286
+ noun: t("Group command", "Comando di gruppo")
87287
+ },
87288
+ "group-status": {
87289
+ scope: "device",
87290
+ noun: t("Group", "Gruppo"),
87291
+ state: [
87292
+ {
87293
+ kind: "numeric",
87294
+ field: "included",
87295
+ quantity: t("the members reporting", "i membri che rispondono"),
87296
+ label: t("Reporting", "Rispondono"),
87297
+ icon: "users"
87298
+ },
87299
+ {
87300
+ kind: "numeric",
87301
+ field: "excluded",
87302
+ quantity: t("the members left out", "i membri esclusi"),
87303
+ label: t("Excluded", "Esclusi"),
87304
+ icon: "users"
87305
+ },
87306
+ {
87307
+ kind: "numeric",
87308
+ field: "total",
87309
+ quantity: t("the member count", "il numero di membri"),
87310
+ label: t("Members", "Membri"),
87311
+ icon: "sigma"
87312
+ }
87313
+ ]
87314
+ },
86701
87315
  "humidity-sensor": {
86702
87316
  scope: "device",
86703
87317
  noun: t("Humidity", "Umidità"),
@@ -88163,6 +88777,16 @@ Object.freeze({
88163
88777
  form: "single",
88164
88778
  optional: false
88165
88779
  }],
88780
+ "groupCommands.getStatus": [{
88781
+ name: "deviceId",
88782
+ form: "single",
88783
+ optional: false
88784
+ }],
88785
+ "groupStatus.getStatus": [{
88786
+ name: "deviceId",
88787
+ form: "single",
88788
+ optional: false
88789
+ }],
88166
88790
  "heatingValve.getStatus": [{
88167
88791
  name: "deviceId",
88168
88792
  form: "single",
@@ -90308,8 +90932,8 @@ var NC_SYSTEM_EVENT_FILTER_KEYS = [
90308
90932
  function systemEventFilterApplies(kind, filter) {
90309
90933
  if (LEGACY_KINDS_WITHOUT_FILTERS.has(kind)) return false;
90310
90934
  switch (filter) {
90311
- case "deviceIds": return kind.startsWith("device-") || kind.startsWith("stream-") || kind === "detection-blind" || kind.startsWith("motion-") || kind.startsWith("recording-") || kind === "alarm-triggered";
90312
- case "deviceTypes": return kind.startsWith("device-") || kind === "detection-blind" || kind.startsWith("motion-");
90935
+ case "deviceIds": return kind.startsWith("device-") || kind.startsWith("stream-") || kind === "detection-blind" || kind.startsWith("motion-") || kind.startsWith("package-llm-") || kind.startsWith("recording-") || kind === "alarm-triggered";
90936
+ case "deviceTypes": return kind.startsWith("device-") || kind === "detection-blind" || kind.startsWith("motion-") || kind.startsWith("package-llm-");
90313
90937
  case "nodeIds": return kind.startsWith("node-") || kind === "addon-crash-loop" || kind === "addon-update-available" || kind === "addon-updated" || kind === "server-update-available" || kind === "wrapper-update-available" || kind === "server-updated" || kind.startsWith("storage-location-") || kind.startsWith("alert-");
90314
90938
  case "packageNames": return kind.endsWith("update-available") || kind === "addon-updated" || kind === "node-updating" || kind === "server-updated";
90315
90939
  case "consumableLowPercent": return NC_CONSUMABLE_SYSTEM_EVENT_KINDS.includes(kind);
@@ -90353,6 +90977,8 @@ var NC_SYSTEM_EVENT_FAMILY = {
90353
90977
  "detection-blind": "device-events",
90354
90978
  "motion-noisy": "device-events",
90355
90979
  "motion-calm": "device-events",
90980
+ "package-llm-silent": "device-events",
90981
+ "package-llm-answered": "device-events",
90356
90982
  "recording-stalled": "device-events",
90357
90983
  "recording-healthy": "device-events",
90358
90984
  "recording-degraded": "device-events",
@@ -90454,6 +91080,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
90454
91080
  label: "Motion without a subject",
90455
91081
  kinds: ["motion-noisy", "motion-calm"]
90456
91082
  },
91083
+ {
91084
+ id: "package-llm",
91085
+ family: "device-events",
91086
+ label: "Package confirm",
91087
+ kinds: ["package-llm-silent", "package-llm-answered"]
91088
+ },
90457
91089
  {
90458
91090
  id: "recording",
90459
91091
  family: "device-events",
@@ -91886,6 +92518,8 @@ var DEVICE_EVENTS = [
91886
92518
  "detection-blind",
91887
92519
  "motion-noisy",
91888
92520
  "motion-calm",
92521
+ "package-llm-silent",
92522
+ "package-llm-answered",
91889
92523
  "recording-stalled",
91890
92524
  "recording-healthy",
91891
92525
  "recording-degraded",
@@ -92489,7 +93123,8 @@ var NC_TEMPLATE_VARS = [
92489
93123
  systemEventKinds: [
92490
93124
  "recording-degraded",
92491
93125
  ...DEVICE_ATTENTION,
92492
- ...ALERT_EPISODE
93126
+ ...ALERT_EPISODE,
93127
+ "package-llm-silent"
92493
93128
  ]
92494
93129
  },
92495
93130
  {
@@ -92582,7 +93217,8 @@ var NC_TEMPLATE_VARS = [
92582
93217
  systemEventKinds: [
92583
93218
  "storage-location-low",
92584
93219
  "storage-location-critical",
92585
- "storage-location-ok"
93220
+ "storage-location-ok",
93221
+ "package-llm-silent"
92586
93222
  ]
92587
93223
  },
92588
93224
  {
@@ -92993,7 +93629,9 @@ var NC_TEMPLATE_HELD_BACK_SYSTEM_EVENT_KINDS = [
92993
93629
  "device-attention-required",
92994
93630
  "device-attention-resolved",
92995
93631
  "rule-broken",
92996
- "rule-repaired"
93632
+ "rule-repaired",
93633
+ "package-llm-silent",
93634
+ "package-llm-answered"
92997
93635
  ];
92998
93636
  /**
92999
93637
  * The catalog as `getTemplateCatalog` SERVES it: every descriptor, with the
@@ -93153,6 +93791,15 @@ var CLASS_BY_KIND = new Map([
93153
93791
  snapshotLabel: "Cameras with constant motion now",
93154
93792
  snapshotSection: null
93155
93793
  },
93794
+ {
93795
+ id: "package-llm-confirm",
93796
+ family: "device-events",
93797
+ label: "Package confirm (not answering / answering again)",
93798
+ bad: ["package-llm-silent"],
93799
+ recovery: ["package-llm-answered"],
93800
+ snapshotLabel: "Cameras whose package confirm is not answering",
93801
+ snapshotSection: null
93802
+ },
93156
93803
  {
93157
93804
  id: "recording-health",
93158
93805
  family: "device-events",