@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
@@ -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
@@ -5632,7 +5640,7 @@ var ZodIssueCode = {
5632
5640
  var ZodFirstPartyTypeKind;
5633
5641
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5634
5642
  //#endregion
5635
- //#region ../types/dist/sleep-CARd6wZF.mjs
5643
+ //#region ../types/dist/sleep-bykKrTgu.mjs
5636
5644
  /**
5637
5645
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5638
5646
  * window to float samples (D455).
@@ -8371,6 +8379,53 @@ var READING_QUANTITIES = [
8371
8379
  ];
8372
8380
  var ReadingQuantitySchema = _enum(READING_QUANTITIES);
8373
8381
  new Set(READING_QUANTITIES);
8382
+ /**
8383
+ * Stored unit symbol for a quantity. `none` means the number is dimensionless
8384
+ * (or an index / ratio / count). `device` means the cap has no single unit.
8385
+ */
8386
+ var QUANTITY_BASE = {
8387
+ temperature: "°C",
8388
+ pressure: "hPa",
8389
+ speed: "m/s",
8390
+ precipitation: "mm",
8391
+ "precipitation-rate": "mm/h",
8392
+ length: "m",
8393
+ area: "m²",
8394
+ illuminance: "lx",
8395
+ irradiance: "W/m²",
8396
+ power: "W",
8397
+ energy: "kWh",
8398
+ voltage: "V",
8399
+ current: "A",
8400
+ "apparent-power": "VA",
8401
+ humidity: "%",
8402
+ percentage: "%",
8403
+ "concentration-volume": "ppm",
8404
+ "concentration-mass": "µg/m³",
8405
+ "concentration-ppb": "ppb",
8406
+ volume: "L",
8407
+ duration: "s",
8408
+ "duration-ms": "ms",
8409
+ information: "B",
8410
+ "sound-level": "dBFS",
8411
+ "signal-level": "dBm",
8412
+ "colour-temperature": "mired",
8413
+ angle: "°",
8414
+ bitrate: "kbps",
8415
+ rate: "fps",
8416
+ mass: "kg",
8417
+ index: "none",
8418
+ ratio: "none",
8419
+ count: "none",
8420
+ none: "none",
8421
+ device: "device"
8422
+ };
8423
+ /** The stored unit, or `undefined` when the quantity has no unit symbol. */
8424
+ function baseUnitOf(quantity) {
8425
+ const symbol = QUANTITY_BASE[quantity];
8426
+ if (symbol === "none" || symbol === "device") return void 0;
8427
+ return symbol;
8428
+ }
8374
8429
  function readingMeta(quantity, extras) {
8375
8430
  return {
8376
8431
  quantity,
@@ -9006,6 +9061,8 @@ var CAP_NAMES = Object.freeze([
9006
9061
  "filesystem-browse",
9007
9062
  "flood",
9008
9063
  "gas",
9064
+ "group-commands",
9065
+ "group-status",
9009
9066
  "heating-valve",
9010
9067
  "humidifier",
9011
9068
  "humidity-sensor",
@@ -9824,6 +9881,20 @@ Object.freeze({
9824
9881
  "path": "detected",
9825
9882
  "valueType": "boolean"
9826
9883
  }],
9884
+ "group-status": [
9885
+ {
9886
+ "path": "included",
9887
+ "valueType": "number"
9888
+ },
9889
+ {
9890
+ "path": "excluded",
9891
+ "valueType": "number"
9892
+ },
9893
+ {
9894
+ "path": "total",
9895
+ "valueType": "number"
9896
+ }
9897
+ ],
9827
9898
  "heating-valve": [{
9828
9899
  "path": "position",
9829
9900
  "valueType": "number"
@@ -10814,7 +10885,7 @@ Object.freeze({
10814
10885
  * can answer "may a rule actuate this?" without importing the schema barrel
10815
10886
  * (~144MB RSS per runner, D28).
10816
10887
  *
10817
- * Coverage: 91 device-scoped capabilities.
10888
+ * Coverage: 93 device-scoped capabilities.
10818
10889
  */
10819
10890
  var DEVICE_SCOPED_CAPS = new Set([
10820
10891
  "accessories",
@@ -10855,6 +10926,8 @@ var DEVICE_SCOPED_CAPS = new Set([
10855
10926
  "feature-probe",
10856
10927
  "flood",
10857
10928
  "gas",
10929
+ "group-commands",
10930
+ "group-status",
10858
10931
  "heating-valve",
10859
10932
  "humidifier",
10860
10933
  "humidity-sensor",
@@ -11306,7 +11379,7 @@ function errMsg(err) {
11306
11379
  return String(err);
11307
11380
  }
11308
11381
  //#endregion
11309
- //#region ../types/dist/composition-kEl9mevu.mjs
11382
+ //#region ../types/dist/composition-OhpuespA.mjs
11310
11383
  /**
11311
11384
  * Deterministic SHA-256 hash of an arbitrary serialisable value. The
11312
11385
  * canonical form sorts object keys alphabetically at every depth so two
@@ -12221,15 +12294,74 @@ function validateExpressionSource(src) {
12221
12294
  }
12222
12295
  return null;
12223
12296
  }
12224
- /** A composed device's stableId is this prefix plus the block id. */
12225
- var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
12226
- /** Longest snippet a `code` source may carry (slice 4). */
12227
- var MAX_COMPOSITION_CODE_LENGTH = 2e4;
12297
+ /**
12298
+ * A composition source identity: `(addonId, stableId)`, never a numeric device
12299
+ * id. Split out so helper schemas can name it without a cycle through
12300
+ * `composition.ts` (D659).
12301
+ */
12228
12302
  var CompositionSourceRefSchema = object({
12229
12303
  /** The owning addon; `stableId` is unique only within it. */
12230
12304
  addonId: string().min(1),
12231
12305
  stableId: string().min(1)
12232
12306
  });
12307
+ var GROUP_TEMPLATE_IDS = [
12308
+ "temperature",
12309
+ "humidity",
12310
+ "pressure",
12311
+ "illuminance",
12312
+ "power",
12313
+ "energy",
12314
+ "battery",
12315
+ "numeric",
12316
+ "motion",
12317
+ "contact",
12318
+ "leak",
12319
+ "smoke",
12320
+ "occupancy",
12321
+ "binary",
12322
+ "switch",
12323
+ "light"
12324
+ ];
12325
+ var NUMERIC_AGGREGATES = [
12326
+ "mean",
12327
+ "median",
12328
+ "min",
12329
+ "max",
12330
+ "sum"
12331
+ ];
12332
+ var BINARY_AGGREGATES = ["any", "all"];
12333
+ /** How an actuator group decides it is on. Unknown members never count as off. */
12334
+ var ACTIVE_CRITERIA = ["at-least-one", "all"];
12335
+ var AGGREGATE_REDUCERS = [
12336
+ "mean",
12337
+ "median",
12338
+ "min",
12339
+ "max",
12340
+ "sum",
12341
+ "any",
12342
+ "all"
12343
+ ];
12344
+ var GroupTemplateIdSchema = _enum(GROUP_TEMPLATE_IDS);
12345
+ var AggregateReducerSchema = _enum(AGGREGATE_REDUCERS);
12346
+ var ActiveCriterionSchema = _enum(ACTIVE_CRITERIA);
12347
+ /** One member. The field is stored so occupancy can name motion or binary. */
12348
+ var HelperMemberSchema = object({
12349
+ source: CompositionSourceRefSchema,
12350
+ cap: string().min(1),
12351
+ fieldPath: string().min(1)
12352
+ });
12353
+ var HelperSpecSchema = discriminatedUnion("kind", [object({
12354
+ kind: literal("group"),
12355
+ templateId: GroupTemplateIdSchema,
12356
+ aggregate: AggregateReducerSchema,
12357
+ members: array(HelperMemberSchema).min(1).max(64),
12358
+ /** Actuator groups only. Readings leave this unset. */
12359
+ active: ActiveCriterionSchema.optional()
12360
+ })]);
12361
+ /** A composed device's stableId is this prefix plus the block id. */
12362
+ var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
12363
+ /** Longest snippet a `code` source may carry (slice 4). */
12364
+ var MAX_COMPOSITION_CODE_LENGTH = 2e4;
12233
12365
  /** One field of one capability of one source device. */
12234
12366
  var CompositionFieldReadSchema = object({
12235
12367
  source: CompositionSourceRefSchema,
@@ -12273,7 +12405,33 @@ var CompositionCodeSourceSchema = object({
12273
12405
  var CompositionFieldSourceSchema = discriminatedUnion("kind", [
12274
12406
  CompositionFromSourceSchema,
12275
12407
  CompositionExpressionSourceSchema,
12276
- CompositionCodeSourceSchema
12408
+ CompositionCodeSourceSchema,
12409
+ object({
12410
+ kind: literal("aggregate"),
12411
+ reducer: _enum([
12412
+ "mean",
12413
+ "median",
12414
+ "min",
12415
+ "max",
12416
+ "sum",
12417
+ "any",
12418
+ "all"
12419
+ ]),
12420
+ reads: array(CompositionFieldReadSchema).min(1).max(64),
12421
+ /** `value` is the reading; the others are the member counts. */
12422
+ publish: _enum([
12423
+ "value",
12424
+ "included",
12425
+ "excluded",
12426
+ "total"
12427
+ ]),
12428
+ /** What a `value` publish does when nobody is included. Counts ignore this. */
12429
+ empty: _enum([
12430
+ "null",
12431
+ "omit",
12432
+ "offline"
12433
+ ])
12434
+ })
12277
12435
  ]);
12278
12436
  var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
12279
12437
  kind: literal("forward"),
@@ -12319,7 +12477,13 @@ var CompositionSchema = object({
12319
12477
  kind: literal("existing"),
12320
12478
  device: CompositionSourceRefSchema
12321
12479
  })]),
12322
- features: array(CompositionFeatureSchema).min(1).max(16)
12480
+ features: array(CompositionFeatureSchema).min(1).max(16),
12481
+ /**
12482
+ * Present when the block is a helper template. Absent on a free
12483
+ * composition (the room example, device 4603). The editor reads this,
12484
+ * never the compiled features.
12485
+ */
12486
+ helper: HelperSpecSchema.optional()
12323
12487
  }).superRefine((composition, ctx) => {
12324
12488
  const seen = /* @__PURE__ */ new Set();
12325
12489
  composition.features.forEach((feature, index) => {
@@ -19311,7 +19475,10 @@ var CompositionProblemSchema = object({
19311
19475
  "target-missing",
19312
19476
  "target-unreadable",
19313
19477
  "not-replaceable",
19314
- "native-capability-replace"
19478
+ "native-capability-replace",
19479
+ "mixed-quantity",
19480
+ "helper-mismatch",
19481
+ "member-constraint"
19315
19482
  ]),
19316
19483
  path: string(),
19317
19484
  message: string()
@@ -19332,7 +19499,8 @@ var CompositionUnavailableModeSchema = _enum([
19332
19499
  "null",
19333
19500
  "offline",
19334
19501
  "unknown",
19335
- "release"
19502
+ "release",
19503
+ "omit"
19336
19504
  ]);
19337
19505
  /**
19338
19506
  * `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
@@ -19546,6 +19714,275 @@ Object.freeze({
19546
19714
  result: ["number", "null"]
19547
19715
  }
19548
19716
  });
19717
+ /**
19718
+ * One catalog row per base reading a group helper can build (D944 §3).
19719
+ * Data, not a form default written into the block.
19720
+ */
19721
+ var NOW = {
19722
+ fieldPath: "lastFetchedAt",
19723
+ expr: "now"
19724
+ };
19725
+ var CHANGED = {
19726
+ fieldPath: "lastChangedAt",
19727
+ expr: "now"
19728
+ };
19729
+ function numeric(input) {
19730
+ return {
19731
+ ...input,
19732
+ family: "numeric",
19733
+ deviceType: DeviceType.Sensor,
19734
+ memberDeviceType: DeviceType.Sensor,
19735
+ commandCaps: [],
19736
+ baseUnit: baseUnitOf(input.quantity),
19737
+ aggregates: NUMERIC_AGGREGATES,
19738
+ accept: [{
19739
+ cap: input.outputCap,
19740
+ fieldPath: input.outputField
19741
+ }]
19742
+ };
19743
+ }
19744
+ function binary(input) {
19745
+ return {
19746
+ ...input,
19747
+ family: "binary",
19748
+ deviceType: DeviceType.Sensor,
19749
+ memberDeviceType: DeviceType.Sensor,
19750
+ commandCaps: [],
19751
+ quantity: "none",
19752
+ baseUnit: void 0,
19753
+ aggregates: BINARY_AGGREGATES,
19754
+ empty: "offline"
19755
+ };
19756
+ }
19757
+ var GROUP_TEMPLATES = [
19758
+ numeric({
19759
+ id: "temperature",
19760
+ summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
19761
+ role: DeviceRole.TemperatureSensor,
19762
+ outputCap: "temperature-sensor",
19763
+ outputField: "celsius",
19764
+ quantity: "temperature",
19765
+ defaultAggregate: "mean",
19766
+ empty: "null",
19767
+ companions: [NOW]
19768
+ }),
19769
+ numeric({
19770
+ id: "humidity",
19771
+ summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
19772
+ role: DeviceRole.HumiditySensor,
19773
+ outputCap: "humidity-sensor",
19774
+ outputField: "percent",
19775
+ quantity: "humidity",
19776
+ defaultAggregate: "mean",
19777
+ empty: "null",
19778
+ companions: [NOW]
19779
+ }),
19780
+ numeric({
19781
+ id: "pressure",
19782
+ summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
19783
+ role: DeviceRole.PressureSensor,
19784
+ outputCap: "pressure-sensor",
19785
+ outputField: "hpa",
19786
+ quantity: "pressure",
19787
+ defaultAggregate: "mean",
19788
+ empty: "null",
19789
+ companions: [NOW]
19790
+ }),
19791
+ numeric({
19792
+ id: "illuminance",
19793
+ summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
19794
+ role: DeviceRole.AmbientLightSensor,
19795
+ outputCap: "ambient-light-sensor",
19796
+ outputField: "lux",
19797
+ quantity: "illuminance",
19798
+ defaultAggregate: "mean",
19799
+ empty: "null",
19800
+ companions: [NOW]
19801
+ }),
19802
+ numeric({
19803
+ id: "power",
19804
+ summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
19805
+ role: DeviceRole.PowerSensor,
19806
+ outputCap: "power-meter",
19807
+ outputField: "watts",
19808
+ quantity: "power",
19809
+ defaultAggregate: "sum",
19810
+ empty: "omit",
19811
+ companions: [NOW]
19812
+ }),
19813
+ numeric({
19814
+ id: "energy",
19815
+ summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
19816
+ role: DeviceRole.EnergySensor,
19817
+ outputCap: "power-meter",
19818
+ outputField: "kwhTotal",
19819
+ quantity: "energy",
19820
+ defaultAggregate: "sum",
19821
+ empty: "omit",
19822
+ companions: [NOW]
19823
+ }),
19824
+ numeric({
19825
+ id: "battery",
19826
+ summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
19827
+ role: DeviceRole.BatterySensor,
19828
+ outputCap: "battery",
19829
+ outputField: "percentage",
19830
+ quantity: "percentage",
19831
+ defaultAggregate: "mean",
19832
+ empty: "null",
19833
+ companions: [
19834
+ {
19835
+ fieldPath: "charging",
19836
+ expr: "\"unknown\""
19837
+ },
19838
+ {
19839
+ fieldPath: "sleeping",
19840
+ expr: "false"
19841
+ },
19842
+ {
19843
+ fieldPath: "lastUpdated",
19844
+ expr: "now"
19845
+ }
19846
+ ]
19847
+ }),
19848
+ numeric({
19849
+ id: "numeric",
19850
+ summary: "A numeric reading in the members’ shared quantity. Mixed quantities are refused. Nobody reporting publishes null, not 0.",
19851
+ role: DeviceRole.NumericSensor,
19852
+ outputCap: "numeric-sensor",
19853
+ outputField: "value",
19854
+ quantity: "device",
19855
+ defaultAggregate: "mean",
19856
+ empty: "null",
19857
+ companions: [NOW]
19858
+ }),
19859
+ binary({
19860
+ id: "motion",
19861
+ summary: "Any or all motion. Offline and unknown members are left out, never read as off. Nobody reporting takes the device offline.",
19862
+ role: DeviceRole.MotionSensor,
19863
+ outputCap: "motion",
19864
+ outputField: "detected",
19865
+ defaultAggregate: "any",
19866
+ accept: [{
19867
+ cap: "motion",
19868
+ fieldPath: "detected"
19869
+ }],
19870
+ companions: [{
19871
+ fieldPath: "lastDetectedAt",
19872
+ expr: "null"
19873
+ }, {
19874
+ fieldPath: "autoClearAfterMs",
19875
+ expr: "null"
19876
+ }]
19877
+ }),
19878
+ binary({
19879
+ id: "contact",
19880
+ summary: "Any or all open contacts. Offline and unknown members are left out, never read as closed.",
19881
+ role: DeviceRole.ContactSensor,
19882
+ outputCap: "contact",
19883
+ outputField: "entryOpen",
19884
+ defaultAggregate: "any",
19885
+ accept: [{
19886
+ cap: "contact",
19887
+ fieldPath: "entryOpen"
19888
+ }],
19889
+ companions: [CHANGED]
19890
+ }),
19891
+ binary({
19892
+ id: "leak",
19893
+ summary: "Any or all leak detections. Offline and unknown members are left out, never read as dry.",
19894
+ role: DeviceRole.LeakSensor,
19895
+ outputCap: "flood",
19896
+ outputField: "flooded",
19897
+ defaultAggregate: "any",
19898
+ accept: [{
19899
+ cap: "flood",
19900
+ fieldPath: "flooded"
19901
+ }],
19902
+ companions: [CHANGED]
19903
+ }),
19904
+ binary({
19905
+ id: "smoke",
19906
+ summary: "Any or all smoke detections. Offline and unknown members are left out, never read as clear.",
19907
+ role: DeviceRole.SmokeSensor,
19908
+ outputCap: "smoke",
19909
+ outputField: "detected",
19910
+ defaultAggregate: "any",
19911
+ accept: [{
19912
+ cap: "smoke",
19913
+ fieldPath: "detected"
19914
+ }],
19915
+ companions: [CHANGED]
19916
+ }),
19917
+ binary({
19918
+ id: "occupancy",
19919
+ summary: "Any or all of motion or binary sensors, published as a binary. Presence zones are not aggregated. Nobody reporting is offline, not off.",
19920
+ role: DeviceRole.BinarySensor,
19921
+ outputCap: "binary",
19922
+ outputField: "on",
19923
+ defaultAggregate: "any",
19924
+ accept: [{
19925
+ cap: "motion",
19926
+ fieldPath: "detected"
19927
+ }, {
19928
+ cap: "binary",
19929
+ fieldPath: "on"
19930
+ }],
19931
+ companions: [CHANGED]
19932
+ }),
19933
+ binary({
19934
+ id: "binary",
19935
+ summary: "Any or all generic binary sensors. Offline and unknown members are left out, never read as off.",
19936
+ role: DeviceRole.BinarySensor,
19937
+ outputCap: "binary",
19938
+ outputField: "on",
19939
+ defaultAggregate: "any",
19940
+ accept: [{
19941
+ cap: "binary",
19942
+ fieldPath: "on"
19943
+ }],
19944
+ companions: [CHANGED]
19945
+ }),
19946
+ actuator({
19947
+ id: "switch",
19948
+ 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.",
19949
+ deviceType: DeviceType.Switch,
19950
+ outputCap: "switch",
19951
+ commandCaps: ["switch"]
19952
+ }),
19953
+ actuator({
19954
+ id: "light",
19955
+ 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.",
19956
+ deviceType: DeviceType.Light,
19957
+ outputCap: "switch",
19958
+ commandCaps: [
19959
+ "switch",
19960
+ "brightness",
19961
+ "color"
19962
+ ]
19963
+ })
19964
+ ];
19965
+ function actuator(input) {
19966
+ return {
19967
+ ...input,
19968
+ family: "actuator",
19969
+ role: void 0,
19970
+ memberDeviceType: input.deviceType,
19971
+ outputField: "on",
19972
+ quantity: "none",
19973
+ baseUnit: void 0,
19974
+ aggregates: BINARY_AGGREGATES,
19975
+ defaultAggregate: "any",
19976
+ empty: "offline",
19977
+ accept: [{
19978
+ cap: "switch",
19979
+ fieldPath: "on"
19980
+ }],
19981
+ companions: [CHANGED]
19982
+ };
19983
+ }
19984
+ new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
19985
+ DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
19549
19986
  `${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
19550
19987
  /**
19551
19988
  * What a composition may BUILD on a device type (G2, D676): the caps a new
@@ -46501,6 +46938,8 @@ var NcSystemEventKindSchema = _enum([
46501
46938
  "detection-blind",
46502
46939
  "motion-noisy",
46503
46940
  "motion-calm",
46941
+ "package-llm-silent",
46942
+ "package-llm-answered",
46504
46943
  "recording-stalled",
46505
46944
  "recording-healthy",
46506
46945
  "recording-degraded",
@@ -48063,6 +48502,14 @@ var NC_CONDITION_CATALOG = [
48063
48502
  value: "motion-calm",
48064
48503
  label: "Camera motion calm again"
48065
48504
  },
48505
+ {
48506
+ value: "package-llm-silent",
48507
+ label: "Package confirm not answering"
48508
+ },
48509
+ {
48510
+ value: "package-llm-answered",
48511
+ label: "Package confirm answering again"
48512
+ },
48066
48513
  {
48067
48514
  value: "recording-stalled",
48068
48515
  label: "Recording stalled"
@@ -59438,6 +59885,28 @@ var PackageVersionInfoSchema = object({
59438
59885
  deprecated: string().optional(),
59439
59886
  distTags: array(string()).readonly()
59440
59887
  });
59888
+ /**
59889
+ * One published document. `ok` is markdown from the registry. `missing` means
59890
+ * the registry answered and the file was not there. `error` is a registry or
59891
+ * tarball failure — never an empty string standing in for either.
59892
+ */
59893
+ var PackageDocBodySchema = discriminatedUnion("status", [
59894
+ object({
59895
+ status: literal("ok"),
59896
+ markdown: string()
59897
+ }),
59898
+ object({ status: literal("missing") }),
59899
+ object({
59900
+ status: literal("error"),
59901
+ message: string()
59902
+ })
59903
+ ]);
59904
+ var PackageDocsSchema = object({
59905
+ name: string(),
59906
+ version: string(),
59907
+ readme: PackageDocBodySchema,
59908
+ changelog: PackageDocBodySchema
59909
+ });
59441
59910
  var SearchResultSchema = object({
59442
59911
  name: string(),
59443
59912
  version: string(),
@@ -59656,7 +60125,10 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
59656
60125
  }), object({ success: literal(true) }), {
59657
60126
  kind: "mutation",
59658
60127
  auth: "admin"
59659
- }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
60128
+ }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
60129
+ name: string().min(1),
60130
+ version: string().min(1).optional()
60131
+ }), PackageDocsSchema, { auth: "admin" }), method(object({ addonId: string() }), RestartAddonResultSchema, {
59660
60132
  kind: "mutation",
59661
60133
  auth: "admin"
59662
60134
  }), method(object({ packageName: string() }), object({ success: literal(true) }), {
@@ -63078,6 +63550,88 @@ var gasCapability = {
63078
63550
  * whether persisting is worth a SQLite commit. */
63079
63551
  volatileStateFields: ["lastChangedAt"]
63080
63552
  };
63553
+ var GroupCommandsSchema = object({
63554
+ /** One row per member that has been commanded. A later command replaces that member's row. */
63555
+ results: array(object({
63556
+ deviceId: number().int().nonnegative(),
63557
+ cap: string().min(1),
63558
+ method: string().min(1),
63559
+ ok: boolean(),
63560
+ error: string().optional(),
63561
+ /** Ms epoch of the attempt. */
63562
+ at: number()
63563
+ })) });
63564
+ var groupCommandsCapability = {
63565
+ name: "group-commands",
63566
+ scope: "device",
63567
+ deviceNative: true,
63568
+ mode: "singleton",
63569
+ deviceTypes: [DeviceType.Switch, DeviceType.Light],
63570
+ methods: {},
63571
+ status: {
63572
+ schema: GroupCommandsSchema,
63573
+ kind: "push"
63574
+ },
63575
+ runtimeState: GroupCommandsSchema,
63576
+ /**
63577
+ * Runtime-state durability: **session** — the last attempt. A restored
63578
+ * failure would outlive the command that caused it.
63579
+ *
63580
+ * See `RuntimeStateDurability`. Enforced by
63581
+ * `scripts/check-runtime-state-durability.ts`.
63582
+ */
63583
+ durability: "session",
63584
+ history: "none"
63585
+ };
63586
+ /**
63587
+ * How many members of a helper group answered (D944). Counts are integers,
63588
+ * not measurements: zero included is a real count, never a stand-in reading.
63589
+ * The reading itself stays on the output capability. History is none — the
63590
+ * series that later statistics read is the output cap's own history block.
63591
+ */
63592
+ var GroupStatusSchema = object({
63593
+ /** Members whose current value entered the aggregate. */
63594
+ included: number().int().nonnegative().meta(readingMeta("count", {
63595
+ precision: 0,
63596
+ label: "Reporting"
63597
+ })),
63598
+ /** Members left out: offline, unknown, or not a finite reading (D393). */
63599
+ excluded: number().int().nonnegative().meta(readingMeta("count", {
63600
+ precision: 0,
63601
+ label: "Excluded"
63602
+ })),
63603
+ /** `included` + `excluded`. */
63604
+ total: number().int().nonnegative().meta(readingMeta("count", {
63605
+ precision: 0,
63606
+ label: "Members"
63607
+ }))
63608
+ });
63609
+ var groupStatusCapability = {
63610
+ name: "group-status",
63611
+ scope: "device",
63612
+ deviceNative: true,
63613
+ mode: "singleton",
63614
+ deviceTypes: [
63615
+ DeviceType.Sensor,
63616
+ DeviceType.Switch,
63617
+ DeviceType.Light
63618
+ ],
63619
+ methods: {},
63620
+ status: {
63621
+ schema: GroupStatusSchema,
63622
+ kind: "push"
63623
+ },
63624
+ runtimeState: GroupStatusSchema,
63625
+ /**
63626
+ * Runtime-state durability: **session** — recomputed from members on the
63627
+ * next source event; a restored count would outlive the readings it named.
63628
+ *
63629
+ * See `RuntimeStateDurability`. Enforced by
63630
+ * `scripts/check-runtime-state-durability.ts`.
63631
+ */
63632
+ durability: "session",
63633
+ history: "none"
63634
+ };
63081
63635
  var HeatingValveStatusSchema = object({
63082
63636
  /** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
63083
63637
  position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
@@ -64893,12 +65447,18 @@ var motionCapability = {
64893
65447
  methods: {
64894
65448
  /**
64895
65449
  * Pull the current motion state synchronously. Convenience shortcut
64896
- * for consumers that don't need the full status object; equivalent
64897
- * to `getStatus()?.detected ?? false`. Will likely be folded into
64898
- * `getStatus` once the auto-injected status surface lands in every
64899
- * consumer.
65450
+ * for consumers that don't need the full status object. A composed
65451
+ * group answers from its slice (D944): unknown throws, it is not off.
64900
65452
  */
64901
65453
  isDetected: method(object({ deviceId: number() }), boolean()) },
65454
+ /**
65455
+ * A composed motion group serves `isDetected` from `detected` (D944).
65456
+ * Without this the cap stays uncomposable (`has-commands`).
65457
+ */
65458
+ composedMethods: { isDetected: {
65459
+ kind: "slice",
65460
+ field: "detected"
65461
+ } },
64902
65462
  events: {
64903
65463
  /**
64904
65464
  * Fires every time the runner transitions a camera between
@@ -72844,6 +73404,8 @@ var DEVICE_LOCAL_STATE_CAPS = {
72844
73404
  featureProbe: featureProbeCapability,
72845
73405
  flood: floodCapability,
72846
73406
  gas: gasCapability,
73407
+ groupCommands: groupCommandsCapability,
73408
+ groupStatus: groupStatusCapability,
72847
73409
  heatingValve: heatingValveCapability,
72848
73410
  humidifier: humidifierCapability,
72849
73411
  humiditySensor: humiditySensorCapability,
@@ -73737,6 +74299,13 @@ Object.freeze({
73737
74299
  access: "view",
73738
74300
  role: "admin"
73739
74301
  },
74302
+ "addons.getPackageDocs": {
74303
+ capName: "addons",
74304
+ capScope: "system",
74305
+ addonId: null,
74306
+ access: "view",
74307
+ role: "admin"
74308
+ },
73740
74309
  "addons.getVersions": {
73741
74310
  capName: "addons",
73742
74311
  capScope: "system",
@@ -76845,6 +77414,20 @@ Object.freeze({
76845
77414
  access: "view",
76846
77415
  role: "viewer"
76847
77416
  },
77417
+ "groupCommands.getStatus": {
77418
+ capName: "group-commands",
77419
+ capScope: "device",
77420
+ addonId: null,
77421
+ access: "view",
77422
+ role: "viewer"
77423
+ },
77424
+ "groupStatus.getStatus": {
77425
+ capName: "group-status",
77426
+ capScope: "device",
77427
+ addonId: null,
77428
+ access: "view",
77429
+ role: "viewer"
77430
+ },
76848
77431
  "heatingValve.getStatus": {
76849
77432
  capName: "heating-valve",
76850
77433
  capScope: "device",
@@ -86667,6 +87250,37 @@ var SENSOR_CAP_VOCABULARY = {
86667
87250
  icon: "flame"
86668
87251
  }]
86669
87252
  },
87253
+ "group-commands": {
87254
+ scope: "device",
87255
+ noun: t("Group command", "Comando di gruppo")
87256
+ },
87257
+ "group-status": {
87258
+ scope: "device",
87259
+ noun: t("Group", "Gruppo"),
87260
+ state: [
87261
+ {
87262
+ kind: "numeric",
87263
+ field: "included",
87264
+ quantity: t("the members reporting", "i membri che rispondono"),
87265
+ label: t("Reporting", "Rispondono"),
87266
+ icon: "users"
87267
+ },
87268
+ {
87269
+ kind: "numeric",
87270
+ field: "excluded",
87271
+ quantity: t("the members left out", "i membri esclusi"),
87272
+ label: t("Excluded", "Esclusi"),
87273
+ icon: "users"
87274
+ },
87275
+ {
87276
+ kind: "numeric",
87277
+ field: "total",
87278
+ quantity: t("the member count", "il numero di membri"),
87279
+ label: t("Members", "Membri"),
87280
+ icon: "sigma"
87281
+ }
87282
+ ]
87283
+ },
86670
87284
  "humidity-sensor": {
86671
87285
  scope: "device",
86672
87286
  noun: t("Humidity", "Umidità"),
@@ -88132,6 +88746,16 @@ Object.freeze({
88132
88746
  form: "single",
88133
88747
  optional: false
88134
88748
  }],
88749
+ "groupCommands.getStatus": [{
88750
+ name: "deviceId",
88751
+ form: "single",
88752
+ optional: false
88753
+ }],
88754
+ "groupStatus.getStatus": [{
88755
+ name: "deviceId",
88756
+ form: "single",
88757
+ optional: false
88758
+ }],
88135
88759
  "heatingValve.getStatus": [{
88136
88760
  name: "deviceId",
88137
88761
  form: "single",
@@ -90277,8 +90901,8 @@ var NC_SYSTEM_EVENT_FILTER_KEYS = [
90277
90901
  function systemEventFilterApplies(kind, filter) {
90278
90902
  if (LEGACY_KINDS_WITHOUT_FILTERS.has(kind)) return false;
90279
90903
  switch (filter) {
90280
- case "deviceIds": return kind.startsWith("device-") || kind.startsWith("stream-") || kind === "detection-blind" || kind.startsWith("motion-") || kind.startsWith("recording-") || kind === "alarm-triggered";
90281
- case "deviceTypes": return kind.startsWith("device-") || kind === "detection-blind" || kind.startsWith("motion-");
90904
+ 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";
90905
+ case "deviceTypes": return kind.startsWith("device-") || kind === "detection-blind" || kind.startsWith("motion-") || kind.startsWith("package-llm-");
90282
90906
  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-");
90283
90907
  case "packageNames": return kind.endsWith("update-available") || kind === "addon-updated" || kind === "node-updating" || kind === "server-updated";
90284
90908
  case "consumableLowPercent": return NC_CONSUMABLE_SYSTEM_EVENT_KINDS.includes(kind);
@@ -90322,6 +90946,8 @@ var NC_SYSTEM_EVENT_FAMILY = {
90322
90946
  "detection-blind": "device-events",
90323
90947
  "motion-noisy": "device-events",
90324
90948
  "motion-calm": "device-events",
90949
+ "package-llm-silent": "device-events",
90950
+ "package-llm-answered": "device-events",
90325
90951
  "recording-stalled": "device-events",
90326
90952
  "recording-healthy": "device-events",
90327
90953
  "recording-degraded": "device-events",
@@ -90423,6 +91049,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
90423
91049
  label: "Motion without a subject",
90424
91050
  kinds: ["motion-noisy", "motion-calm"]
90425
91051
  },
91052
+ {
91053
+ id: "package-llm",
91054
+ family: "device-events",
91055
+ label: "Package confirm",
91056
+ kinds: ["package-llm-silent", "package-llm-answered"]
91057
+ },
90426
91058
  {
90427
91059
  id: "recording",
90428
91060
  family: "device-events",
@@ -91855,6 +92487,8 @@ var DEVICE_EVENTS = [
91855
92487
  "detection-blind",
91856
92488
  "motion-noisy",
91857
92489
  "motion-calm",
92490
+ "package-llm-silent",
92491
+ "package-llm-answered",
91858
92492
  "recording-stalled",
91859
92493
  "recording-healthy",
91860
92494
  "recording-degraded",
@@ -92458,7 +93092,8 @@ var NC_TEMPLATE_VARS = [
92458
93092
  systemEventKinds: [
92459
93093
  "recording-degraded",
92460
93094
  ...DEVICE_ATTENTION,
92461
- ...ALERT_EPISODE
93095
+ ...ALERT_EPISODE,
93096
+ "package-llm-silent"
92462
93097
  ]
92463
93098
  },
92464
93099
  {
@@ -92551,7 +93186,8 @@ var NC_TEMPLATE_VARS = [
92551
93186
  systemEventKinds: [
92552
93187
  "storage-location-low",
92553
93188
  "storage-location-critical",
92554
- "storage-location-ok"
93189
+ "storage-location-ok",
93190
+ "package-llm-silent"
92555
93191
  ]
92556
93192
  },
92557
93193
  {
@@ -92962,7 +93598,9 @@ var NC_TEMPLATE_HELD_BACK_SYSTEM_EVENT_KINDS = [
92962
93598
  "device-attention-required",
92963
93599
  "device-attention-resolved",
92964
93600
  "rule-broken",
92965
- "rule-repaired"
93601
+ "rule-repaired",
93602
+ "package-llm-silent",
93603
+ "package-llm-answered"
92966
93604
  ];
92967
93605
  /**
92968
93606
  * The catalog as `getTemplateCatalog` SERVES it: every descriptor, with the
@@ -93122,6 +93760,15 @@ var CLASS_BY_KIND = new Map([
93122
93760
  snapshotLabel: "Cameras with constant motion now",
93123
93761
  snapshotSection: null
93124
93762
  },
93763
+ {
93764
+ id: "package-llm-confirm",
93765
+ family: "device-events",
93766
+ label: "Package confirm (not answering / answering again)",
93767
+ bad: ["package-llm-silent"],
93768
+ recovery: ["package-llm-answered"],
93769
+ snapshotLabel: "Cameras whose package confirm is not answering",
93770
+ snapshotSection: null
93771
+ },
93125
93772
  {
93126
93773
  id: "recording-health",
93127
93774
  family: "device-events",