@camstack/system 1.2.486 → 1.2.487

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 (86) hide show
  1. package/dist/{agent-https-DP-Ds2hU.js → agent-https-0EEnqeUL.js} +1 -1
  2. package/dist/{agent-https-C4PLR74Z.mjs → agent-https-C24nO-la.mjs} +1 -1
  3. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  4. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  5. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  6. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  7. package/dist/builtins/alerts/alerts.addon.js +1 -1
  8. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  9. package/dist/builtins/autotrack/index.js +1 -1
  10. package/dist/builtins/autotrack/index.mjs +1 -1
  11. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +2 -2
  12. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2 -2
  13. package/dist/builtins/calendars/calendars.addon.js +1 -1
  14. package/dist/builtins/calendars/calendars.addon.mjs +1 -1
  15. package/dist/builtins/camera-grid/index.js +1 -1
  16. package/dist/builtins/camera-grid/index.mjs +1 -1
  17. package/dist/builtins/composer/actuator-dispatch.d.ts +13 -0
  18. package/dist/builtins/composer/actuator-groups.d.ts +54 -0
  19. package/dist/builtins/composer/actuator-invoke.d.ts +11 -0
  20. package/dist/builtins/composer/composed-device.d.ts +13 -24
  21. package/dist/builtins/composer/composer.addon.js +408 -8
  22. package/dist/builtins/composer/composer.addon.mjs +408 -8
  23. package/dist/builtins/composer/composer.d.ts +11 -1
  24. package/dist/builtins/console-logging/index.js +1 -1
  25. package/dist/builtins/console-logging/index.mjs +1 -1
  26. package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
  27. package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
  28. package/dist/builtins/device-history/device-history.addon.js +2 -2
  29. package/dist/builtins/device-history/device-history.addon.mjs +2 -2
  30. package/dist/builtins/device-manager/device-manager.addon.js +1 -1
  31. package/dist/builtins/device-manager/device-manager.addon.mjs +1 -1
  32. package/dist/builtins/hub-forwarder/index.js +1 -1
  33. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  34. package/dist/builtins/keychain/index.js +3 -3
  35. package/dist/builtins/keychain/index.mjs +3 -3
  36. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  37. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  38. package/dist/builtins/local-auth/local-auth.addon.js +2 -2
  39. package/dist/builtins/local-auth/local-auth.addon.mjs +2 -2
  40. package/dist/builtins/local-network/local-network.addon.js +2 -2
  41. package/dist/builtins/local-network/local-network.addon.mjs +2 -2
  42. package/dist/builtins/loki-logging/index.js +1 -1
  43. package/dist/builtins/loki-logging/index.mjs +1 -1
  44. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  45. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  46. package/dist/builtins/platform-probe/index.js +1 -1
  47. package/dist/builtins/platform-probe/index.mjs +1 -1
  48. package/dist/builtins/record-entries/index.js +1 -1
  49. package/dist/builtins/record-entries/index.mjs +1 -1
  50. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  51. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  52. package/dist/builtins/snapshot/index.js +1 -1
  53. package/dist/builtins/snapshot/index.mjs +1 -1
  54. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  55. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  56. package/dist/builtins/sqlite-storage/index.js +1 -1
  57. package/dist/builtins/sqlite-storage/index.mjs +1 -1
  58. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +2 -2
  59. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +2 -2
  60. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  61. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  62. package/dist/builtins/system-config/system-config.addon.js +3 -3
  63. package/dist/builtins/system-config/system-config.addon.mjs +284 -284
  64. package/dist/builtins/winston-logging/index.js +1 -1
  65. package/dist/builtins/winston-logging/index.mjs +1 -1
  66. package/dist/{composition-sources-IxiUkrz1.mjs → composition-sources-BA2e5vh_.mjs} +1 -1
  67. package/dist/{composition-sources-CN8K2Q91.js → composition-sources-BulDAgW2.js} +1 -1
  68. package/dist/{constants-1S7BBGMb.js → constants-BntdWx4k.js} +1 -1
  69. package/dist/{constants-DLyGFHZ2.mjs → constants-DZKo4kM2.mjs} +1 -1
  70. package/dist/{device-ca-DoOFG0nm.js → device-ca-BuRg4V4x.js} +1 -1
  71. package/dist/{device-ca-Cbf7_R9t.mjs → device-ca-DXm8IH3p.mjs} +1 -1
  72. package/dist/{dist-D-d_UWL4.js → dist-CrsVjBbk.js} +375 -15
  73. package/dist/{dist-HBue971z.mjs → dist-Dfwxsc_Y.mjs} +310 -16
  74. package/dist/file-host-worker.js +1 -1
  75. package/dist/file-host-worker.mjs +1 -1
  76. package/dist/{hub-mdns-ciao-CuEWb6gB.mjs → hub-mdns-ciao-BbI8MNtQ.mjs} +2 -2
  77. package/dist/{hub-mdns-ciao-dcacrwqd.js → hub-mdns-ciao-CLroVKhP.js} +2 -2
  78. package/dist/index.js +7 -7
  79. package/dist/index.mjs +7 -7
  80. package/dist/{restore-archive-BGBRadFJ.mjs → restore-archive-BB5QxUIe.mjs} +82 -82
  81. package/dist/{restore-archive-DHdXrKwG.js → restore-archive-CPoja7N3.js} +1 -1
  82. package/dist/{retention-ChgrkTfz.js → retention-DgA4qLBj.js} +1 -1
  83. package/dist/{retention-8uqDWll8.mjs → retention-Dz5t6cWO.mjs} +1 -1
  84. package/dist/{wal-maintenance-DubGwqz2.mjs → wal-maintenance-BJi3_DBN.mjs} +0 -0
  85. package/dist/{wal-maintenance-BOT7wWvH.js → wal-maintenance-CL9hrbnn.js} +0 -0
  86. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  let zod = require("zod");
2
2
  require("node:crypto");
3
- //#region ../types/dist/event-category-DHXxB8t9.mjs
3
+ //#region ../types/dist/event-category-CT-hz5Rb.mjs
4
4
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
5
5
  EventCategory["SystemBoot"] = "system.boot";
6
6
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -326,6 +326,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
326
326
  /** The recovery edge of {@link PipelineMotionNoisy}: the motion fell back, or a detection arrived. */
327
327
  EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
328
328
  /**
329
+ * A camera's package LLM confirm has failed closed three times in a row
330
+ * (D931, 2026-10-26). One edge per camera until
331
+ * {@link PipelinePackageLlmAnswered}.
332
+ */
333
+ EventCategory["PipelinePackageLlmSilent"] = "pipeline.package-llm-silent";
334
+ /** The recovery edge of {@link PipelinePackageLlmSilent}: a confirm returned yes or no. */
335
+ EventCategory["PipelinePackageLlmAnswered"] = "pipeline.package-llm-answered";
336
+ /**
329
337
  * Per-camera pipeline config was mutated by the orchestrator
330
338
  * (a settings change via `setAgentInferenceDevices` /
331
339
  * `setCameraStepToggle` / `setCameraStepSettings`). Orchestrator
@@ -765,7 +773,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
765
773
  return EventCategory;
766
774
  }({});
767
775
  //#endregion
768
- //#region ../types/dist/sleep-B81gwQuR.mjs
776
+ //#region ../types/dist/sleep-bykKrTgu.mjs
769
777
  /**
770
778
  * The audio chunk plane's byte format, and the ONE expansion from a coded
771
779
  * window to float samples (D455).
@@ -5183,6 +5191,7 @@ var CAP_NAMES = Object.freeze([
5183
5191
  "filesystem-browse",
5184
5192
  "flood",
5185
5193
  "gas",
5194
+ "group-commands",
5186
5195
  "group-status",
5187
5196
  "heating-valve",
5188
5197
  "humidifier",
@@ -7483,7 +7492,7 @@ function errMsg(err) {
7483
7492
  return String(err);
7484
7493
  }
7485
7494
  //#endregion
7486
- //#region ../types/dist/composition-B85l9j1M.mjs
7495
+ //#region ../types/dist/composition-OhpuespA.mjs
7487
7496
  var AUDIO_ENCODER_BY_CODEC = {
7488
7497
  opus: "libopus",
7489
7498
  aac: "aac",
@@ -9024,7 +9033,9 @@ var GROUP_TEMPLATE_IDS = [
9024
9033
  "leak",
9025
9034
  "smoke",
9026
9035
  "occupancy",
9027
- "binary"
9036
+ "binary",
9037
+ "switch",
9038
+ "light"
9028
9039
  ];
9029
9040
  var NUMERIC_AGGREGATES = [
9030
9041
  "mean",
@@ -9034,6 +9045,8 @@ var NUMERIC_AGGREGATES = [
9034
9045
  "sum"
9035
9046
  ];
9036
9047
  var BINARY_AGGREGATES = ["any", "all"];
9048
+ /** How an actuator group decides it is on. Unknown members never count as off. */
9049
+ var ACTIVE_CRITERIA = ["at-least-one", "all"];
9037
9050
  var AGGREGATE_REDUCERS = [
9038
9051
  "mean",
9039
9052
  "median",
@@ -9045,6 +9058,7 @@ var AGGREGATE_REDUCERS = [
9045
9058
  ];
9046
9059
  var GroupTemplateIdSchema = zod.z.enum(GROUP_TEMPLATE_IDS);
9047
9060
  var AggregateReducerSchema = zod.z.enum(AGGREGATE_REDUCERS);
9061
+ var ActiveCriterionSchema = zod.z.enum(ACTIVE_CRITERIA);
9048
9062
  /** One member. The field is stored so occupancy can name motion or binary. */
9049
9063
  var HelperMemberSchema = zod.z.object({
9050
9064
  source: CompositionSourceRefSchema,
@@ -9059,7 +9073,9 @@ var GroupHelperSpecSchema = zod.z.object({
9059
9073
  kind: zod.z.literal("group"),
9060
9074
  templateId: GroupTemplateIdSchema,
9061
9075
  aggregate: AggregateReducerSchema,
9062
- members: zod.z.array(HelperMemberSchema).min(1).max(64)
9076
+ members: zod.z.array(HelperMemberSchema).min(1).max(64),
9077
+ /** Actuator groups only. Readings leave this unset. */
9078
+ active: ActiveCriterionSchema.optional()
9063
9079
  });
9064
9080
  var HelperSpecSchema = zod.z.discriminatedUnion("kind", [GroupHelperSpecSchema]);
9065
9081
  /**
@@ -18121,6 +18137,7 @@ function numeric(input) {
18121
18137
  family: "numeric",
18122
18138
  deviceType: DeviceType.Sensor,
18123
18139
  memberDeviceType: DeviceType.Sensor,
18140
+ commandCaps: [],
18124
18141
  baseUnit: baseUnitOf(input.quantity),
18125
18142
  aggregates: NUMERIC_AGGREGATES,
18126
18143
  accept: [{
@@ -18135,6 +18152,7 @@ function binary(input) {
18135
18152
  family: "binary",
18136
18153
  deviceType: DeviceType.Sensor,
18137
18154
  memberDeviceType: DeviceType.Sensor,
18155
+ commandCaps: [],
18138
18156
  quantity: "none",
18139
18157
  baseUnit: void 0,
18140
18158
  aggregates: BINARY_AGGREGATES,
@@ -18329,12 +18347,131 @@ var GROUP_TEMPLATES = [
18329
18347
  fieldPath: "on"
18330
18348
  }],
18331
18349
  companions: [CHANGED]
18350
+ }),
18351
+ actuator({
18352
+ id: "switch",
18353
+ 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.",
18354
+ deviceType: DeviceType.Switch,
18355
+ outputCap: "switch",
18356
+ commandCaps: ["switch"]
18357
+ }),
18358
+ actuator({
18359
+ id: "light",
18360
+ 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.",
18361
+ deviceType: DeviceType.Light,
18362
+ outputCap: "switch",
18363
+ commandCaps: [
18364
+ "switch",
18365
+ "brightness",
18366
+ "color"
18367
+ ]
18332
18368
  })
18333
18369
  ];
18370
+ function actuator(input) {
18371
+ return {
18372
+ ...input,
18373
+ family: "actuator",
18374
+ role: void 0,
18375
+ memberDeviceType: input.deviceType,
18376
+ outputField: "on",
18377
+ quantity: "none",
18378
+ baseUnit: void 0,
18379
+ aggregates: BINARY_AGGREGATES,
18380
+ defaultAggregate: "any",
18381
+ empty: "offline",
18382
+ accept: [{
18383
+ cap: "switch",
18384
+ fieldPath: "on"
18385
+ }],
18386
+ companions: [CHANGED]
18387
+ };
18388
+ }
18334
18389
  var BY_ID = new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
18335
18390
  function groupTemplate(id) {
18336
18391
  return BY_ID.get(id) ?? null;
18337
18392
  }
18393
+ /**
18394
+ * Actuator groups (D944 phase 1b). The active boolean is the binary reducer
18395
+ * with unknown members left out. A command is one call per member that binds
18396
+ * the cap, including members that are offline. One failure does not cancel
18397
+ * the others.
18398
+ */
18399
+ /** Caps a light group may expose, in display order. Switch is the active state. */
18400
+ var LIGHT_SHARED_CAPS = [
18401
+ "switch",
18402
+ "brightness",
18403
+ "color"
18404
+ ];
18405
+ var COLOR_MODE_FEATURES = [
18406
+ DeviceFeature.LightColorRgb,
18407
+ DeviceFeature.LightColorHsv,
18408
+ DeviceFeature.LightColorMired
18409
+ ];
18410
+ /** `at-least-one` is any included member on; `all` is every included member on. */
18411
+ function reducerForActive(active) {
18412
+ return active === "all" ? "all" : "any";
18413
+ }
18414
+ /**
18415
+ * Caps every member binds, from {@link LIGHT_SHARED_CAPS}. An empty member
18416
+ * list shares nothing. A member that lacks colour drops colour from the group.
18417
+ */
18418
+ function sharedLightCaps(memberCaps) {
18419
+ if (memberCaps.length === 0) return [];
18420
+ return LIGHT_SHARED_CAPS.filter((cap) => memberCaps.every((bound) => bound.includes(cap)));
18421
+ }
18422
+ /**
18423
+ * Colour modes every member advertises. Offline does not remove a mode:
18424
+ * the caller passes device features, not liveness. No members → no mode.
18425
+ */
18426
+ function sharedColorModes(memberFeatures) {
18427
+ if (memberFeatures.length === 0) return [];
18428
+ return COLOR_MODE_FEATURES.filter((mode) => memberFeatures.every((features) => features.includes(mode)));
18429
+ }
18430
+ /**
18431
+ * One call per member that binds `cap`. Offline members stay in the list.
18432
+ * A member without the cap is not called — the command cannot reach it.
18433
+ */
18434
+ function fanOutTargets(members, cap, method, args) {
18435
+ return members.flatMap((member) => member.caps.includes(cap) ? [{
18436
+ deviceId: member.deviceId,
18437
+ cap,
18438
+ method,
18439
+ args: { ...args }
18440
+ }] : []);
18441
+ }
18442
+ /**
18443
+ * Run every call. A throw is that member's result; the other calls still run.
18444
+ * At most {@link FAN_OUT_CONCURRENCY} are in flight.
18445
+ */
18446
+ async function runFanOut(calls, invoke) {
18447
+ const results = [];
18448
+ let next = 0;
18449
+ const worker = async () => {
18450
+ for (;;) {
18451
+ const index = next;
18452
+ next += 1;
18453
+ const call = calls[index];
18454
+ if (call === void 0) return;
18455
+ try {
18456
+ await invoke(call);
18457
+ results[index] = {
18458
+ deviceId: call.deviceId,
18459
+ ok: true
18460
+ };
18461
+ } catch (err) {
18462
+ const error = err instanceof Error ? err.message : String(err);
18463
+ results[index] = {
18464
+ deviceId: call.deviceId,
18465
+ ok: false,
18466
+ error
18467
+ };
18468
+ }
18469
+ }
18470
+ };
18471
+ const width = Math.min(4, calls.length);
18472
+ await Promise.all(Array.from({ length: width }, () => worker()));
18473
+ return results;
18474
+ }
18338
18475
  function sameSource(a, b) {
18339
18476
  return a.addonId === b.addonId && a.stableId === b.stableId;
18340
18477
  }
@@ -18383,7 +18520,7 @@ function draftOf$1(template, spec) {
18383
18520
  target: {
18384
18521
  kind: "new",
18385
18522
  type: template.deviceType,
18386
- role: template.role
18523
+ ...template.role === void 0 ? {} : { role: template.role }
18387
18524
  },
18388
18525
  helper: spec,
18389
18526
  features: [{
@@ -18404,6 +18541,16 @@ function draftOf$1(template, spec) {
18404
18541
  }]
18405
18542
  };
18406
18543
  }
18544
+ function criterionProblems(template, spec) {
18545
+ if (template.family === "actuator") {
18546
+ if (spec.active === void 0) return [problem("kind-mismatch", "helper.active", `a ${template.id} group needs an active criterion (at-least-one or all)`)];
18547
+ const reducer = reducerForActive(spec.active);
18548
+ if (spec.aggregate !== reducer) return [problem("kind-mismatch", "helper.aggregate", `active \`${spec.active}\` aggregates by \`${reducer}\`, not \`${spec.aggregate}\``)];
18549
+ return [];
18550
+ }
18551
+ if (spec.active !== void 0) return [problem("kind-mismatch", "helper.active", `a ${template.id} group has no active criterion — that belongs to an actuator group`)];
18552
+ return [];
18553
+ }
18407
18554
  function parseDraft(draft) {
18408
18555
  const parsed = CompositionSchema.safeParse(draft);
18409
18556
  if (parsed.success) return {
@@ -18422,6 +18569,11 @@ function compileHelper(spec) {
18422
18569
  ok: false,
18423
18570
  problems: [problem("member-constraint", "helper.templateId", `unknown template \`${spec.templateId}\``)]
18424
18571
  };
18572
+ const criterion = criterionProblems(template, spec);
18573
+ if (criterion.length > 0) return {
18574
+ ok: false,
18575
+ problems: criterion
18576
+ };
18425
18577
  if (!template.aggregates.includes(spec.aggregate)) {
18426
18578
  const allowed = template.aggregates.join(", ");
18427
18579
  return {
@@ -18657,11 +18809,22 @@ function composableCap(feature, at, lookupCap) {
18657
18809
  * required field. A REPLACE needs none of it: the cap is bound (a fact), the
18658
18810
  * native keeps serving its methods, and only the named fields are owned (D663).
18659
18811
  */
18660
- function builtCapProblems({ def, state, fields: targetFields }, feature, at, deviceType) {
18812
+ /**
18813
+ * Caps an actuator helper is allowed to serve. A free composition, and a
18814
+ * reading group, get an empty set — `has-commands` stays for them.
18815
+ */
18816
+ function actuatorCommandCaps(composition) {
18817
+ const spec = composition.helper;
18818
+ if (spec === void 0) return /* @__PURE__ */ new Set();
18819
+ const template = groupTemplate(spec.templateId);
18820
+ if (template === null || template.family !== "actuator") return /* @__PURE__ */ new Set();
18821
+ return new Set(template.commandCaps);
18822
+ }
18823
+ function builtCapProblems({ def, state, fields: targetFields }, feature, at, deviceType, servedCommands) {
18661
18824
  const problems = [];
18662
18825
  if (def.deviceTypes !== void 0 && !def.deviceTypes.includes(deviceType)) problems.push(problem("wrong-device-type", `${at}.cap`, `\`${def.name}\` is not offered on a \`${deviceType}\` device (it allows ${def.deviceTypes.join(", ")})`));
18663
18826
  const served = Object.entries(def.methods).filter(([name, m]) => m.systemOnly !== true && def.composedMethods?.[name] === void 0).map(([name]) => `\`${name}\``);
18664
- if (served.length > 0) problems.push(problem("has-commands", `${at}.cap`, `\`${def.name}\` has ${served.join(", ")}, which a composed device cannot serve until commands arrive (slice 3)`));
18827
+ if (served.length > 0 && !servedCommands.has(def.name)) problems.push(problem("has-commands", `${at}.cap`, `\`${def.name}\` has ${served.join(", ")}, which a composed device cannot serve until commands arrive (slice 3)`));
18665
18828
  const itemArrayPath = feature.items === void 0 ? null : def.status?.itemArray?.path ?? null;
18666
18829
  for (const key of requiredTopLevelKeys(state)) {
18667
18830
  if (key === itemArrayPath) continue;
@@ -18702,11 +18865,11 @@ function planTopLevelField({ def, fields }, field, mode, lookupCap) {
18702
18865
  events: []
18703
18866
  };
18704
18867
  }
18705
- function planFeature(feature, featureIndex, target, lookupCap) {
18868
+ function planFeature(feature, featureIndex, target, lookupCap, servedCommands) {
18706
18869
  const at = `features[${featureIndex}]`;
18707
18870
  const cap = composableCap(feature, at, lookupCap);
18708
18871
  if ("code" in cap) return refused(cap);
18709
- const capProblems = target.mode === "replace" ? [] : [...builtCapProblems(cap, feature, at, target.deviceType)];
18872
+ const capProblems = target.mode === "replace" ? [] : [...builtCapProblems(cap, feature, at, target.deviceType, servedCommands)];
18710
18873
  if (feature.commands !== void 0 && Object.keys(feature.commands).length > 0) capProblems.push(problem("reserved-variant", `${at}.commands`, "commands (`forward`) arrive in slice 3"));
18711
18874
  const perField = Object.entries(feature.fields).map(([path, source]) => planTopLevelField(cap, {
18712
18875
  featureIndex,
@@ -18792,6 +18955,7 @@ function featureTargetOf(target, cap, at) {
18792
18955
  function planComposition(composition, lookupCap, target) {
18793
18956
  const planTarget = planTargetOf(composition, target);
18794
18957
  if ("code" in planTarget) return refused(planTarget);
18958
+ const servedCommands = actuatorCommandCaps(composition);
18795
18959
  const results = composition.features.map((feature, index) => {
18796
18960
  const at = `features[${index}]`;
18797
18961
  if (feature.kind === "passthrough") return refused(problem("reserved-variant", at, `whole-capability passthrough of \`${feature.cap}\` arrives in slice 3`));
@@ -18806,9 +18970,9 @@ function planComposition(composition, lookupCap, target) {
18806
18970
  return nativeReplaceOrBlock(featureTarget, planFeature(feature, index, {
18807
18971
  mode: "add",
18808
18972
  deviceType: planTarget.found.type
18809
- }, lookupCap));
18973
+ }, lookupCap, servedCommands));
18810
18974
  }
18811
- const result = planFeature(feature, index, featureTarget, lookupCap);
18975
+ const result = planFeature(feature, index, featureTarget, lookupCap, servedCommands);
18812
18976
  return compositionFeatureEnabled(feature) ? result : {
18813
18977
  problems: result.problems,
18814
18978
  fields: [],
@@ -48260,6 +48424,8 @@ var NcSystemEventKindSchema = zod.z.enum([
48260
48424
  "detection-blind",
48261
48425
  "motion-noisy",
48262
48426
  "motion-calm",
48427
+ "package-llm-silent",
48428
+ "package-llm-answered",
48263
48429
  "recording-stalled",
48264
48430
  "recording-healthy",
48265
48431
  "recording-degraded",
@@ -62225,6 +62391,28 @@ var PackageVersionInfoSchema = zod.z.object({
62225
62391
  deprecated: zod.z.string().optional(),
62226
62392
  distTags: zod.z.array(zod.z.string()).readonly()
62227
62393
  });
62394
+ /**
62395
+ * One published document. `ok` is markdown from the registry. `missing` means
62396
+ * the registry answered and the file was not there. `error` is a registry or
62397
+ * tarball failure — never an empty string standing in for either.
62398
+ */
62399
+ var PackageDocBodySchema = zod.z.discriminatedUnion("status", [
62400
+ zod.z.object({
62401
+ status: zod.z.literal("ok"),
62402
+ markdown: zod.z.string()
62403
+ }),
62404
+ zod.z.object({ status: zod.z.literal("missing") }),
62405
+ zod.z.object({
62406
+ status: zod.z.literal("error"),
62407
+ message: zod.z.string()
62408
+ })
62409
+ ]);
62410
+ var PackageDocsSchema = zod.z.object({
62411
+ name: zod.z.string(),
62412
+ version: zod.z.string(),
62413
+ readme: PackageDocBodySchema,
62414
+ changelog: PackageDocBodySchema
62415
+ });
62228
62416
  var SearchResultSchema = zod.z.object({
62229
62417
  name: zod.z.string(),
62230
62418
  version: zod.z.string(),
@@ -62591,6 +62779,15 @@ var addonsCapability = {
62591
62779
  auth: "admin"
62592
62780
  }),
62593
62781
  getVersions: method(zod.z.object({ name: zod.z.string() }), zod.z.array(PackageVersionInfoSchema).readonly()),
62782
+ /**
62783
+ * README and CHANGELOG for one registry package, read on the hub and
62784
+ * cached. `version` omitted resolves the `latest` dist-tag. The browser
62785
+ * never talks to the registry.
62786
+ */
62787
+ getPackageDocs: method(zod.z.object({
62788
+ name: zod.z.string().min(1),
62789
+ version: zod.z.string().min(1).optional()
62790
+ }), PackageDocsSchema, { auth: "admin" }),
62594
62791
  restartAddon: method(zod.z.object({ addonId: zod.z.string() }), RestartAddonResultSchema, {
62595
62792
  kind: "mutation",
62596
62793
  auth: "admin"
@@ -64088,6 +64285,10 @@ var ColorStatusSchema = zod.z.object({
64088
64285
  /** Ms epoch of the last operator-driven change. */
64089
64286
  lastChangedAt: zod.z.number()
64090
64287
  });
64288
+ function parseColorInput(value) {
64289
+ const parsed = ColorInputSchema.safeParse(value);
64290
+ return parsed.success ? parsed.data : null;
64291
+ }
64091
64292
  var colorCapability = {
64092
64293
  name: "color",
64093
64294
  scope: "device",
@@ -66165,6 +66366,46 @@ var gasCapability = {
66165
66366
  volatileStateFields: ["lastChangedAt"]
66166
66367
  };
66167
66368
  /**
66369
+ * The last command a helper actuator group sent to each member (D944).
66370
+ * The composer writes this slice; the aggregate pass does not, so a later
66371
+ * reading does not wipe it. History is none — the outcome is the latest
66372
+ * attempt, not a series.
66373
+ */
66374
+ var GroupCommandResultSchema = zod.z.object({
66375
+ deviceId: zod.z.number().int().nonnegative(),
66376
+ cap: zod.z.string().min(1),
66377
+ method: zod.z.string().min(1),
66378
+ ok: zod.z.boolean(),
66379
+ error: zod.z.string().optional(),
66380
+ /** Ms epoch of the attempt. */
66381
+ at: zod.z.number()
66382
+ });
66383
+ var GroupCommandsSchema = zod.z.object({
66384
+ /** One row per member that has been commanded. A later command replaces that member's row. */
66385
+ results: zod.z.array(GroupCommandResultSchema) });
66386
+ var groupCommandsCapability = {
66387
+ name: "group-commands",
66388
+ scope: "device",
66389
+ deviceNative: true,
66390
+ mode: "singleton",
66391
+ deviceTypes: [DeviceType.Switch, DeviceType.Light],
66392
+ methods: {},
66393
+ status: {
66394
+ schema: GroupCommandsSchema,
66395
+ kind: "push"
66396
+ },
66397
+ runtimeState: GroupCommandsSchema,
66398
+ /**
66399
+ * Runtime-state durability: **session** — the last attempt. A restored
66400
+ * failure would outlive the command that caused it.
66401
+ *
66402
+ * See `RuntimeStateDurability`. Enforced by
66403
+ * `scripts/check-runtime-state-durability.ts`.
66404
+ */
66405
+ durability: "session",
66406
+ history: "none"
66407
+ };
66408
+ /**
66168
66409
  * How many members of a helper group answered (D944). Counts are integers,
66169
66410
  * not measurements: zero included is a real count, never a stand-in reading.
66170
66411
  * The reading itself stays on the output capability. History is none — the
@@ -66192,7 +66433,11 @@ var groupStatusCapability = {
66192
66433
  scope: "device",
66193
66434
  deviceNative: true,
66194
66435
  mode: "singleton",
66195
- deviceTypes: [DeviceType.Sensor],
66436
+ deviceTypes: [
66437
+ DeviceType.Sensor,
66438
+ DeviceType.Switch,
66439
+ DeviceType.Light
66440
+ ],
66196
66441
  methods: {},
66197
66442
  status: {
66198
66443
  schema: GroupStatusSchema,
@@ -78179,6 +78424,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
78179
78424
  featureProbe: featureProbeCapability,
78180
78425
  flood: floodCapability,
78181
78426
  gas: gasCapability,
78427
+ groupCommands: groupCommandsCapability,
78182
78428
  groupStatus: groupStatusCapability,
78183
78429
  heatingValve: heatingValveCapability,
78184
78430
  humidifier: humidifierCapability,
@@ -79334,6 +79580,13 @@ var METHOD_ACCESS_MAP = Object.freeze({
79334
79580
  access: "view",
79335
79581
  role: "admin"
79336
79582
  },
79583
+ "addons.getPackageDocs": {
79584
+ capName: "addons",
79585
+ capScope: "system",
79586
+ addonId: null,
79587
+ access: "view",
79588
+ role: "admin"
79589
+ },
79337
79590
  "addons.getVersions": {
79338
79591
  capName: "addons",
79339
79592
  capScope: "system",
@@ -82442,6 +82695,13 @@ var METHOD_ACCESS_MAP = Object.freeze({
82442
82695
  access: "view",
82443
82696
  role: "viewer"
82444
82697
  },
82698
+ "groupCommands.getStatus": {
82699
+ capName: "group-commands",
82700
+ capScope: "device",
82701
+ addonId: null,
82702
+ access: "view",
82703
+ role: "viewer"
82704
+ },
82445
82705
  "groupStatus.getStatus": {
82446
82706
  capName: "group-status",
82447
82707
  capScope: "device",
@@ -92271,6 +92531,10 @@ var SENSOR_CAP_VOCABULARY = {
92271
92531
  icon: "flame"
92272
92532
  }]
92273
92533
  },
92534
+ "group-commands": {
92535
+ scope: "device",
92536
+ noun: t("Group command", "Comando di gruppo")
92537
+ },
92274
92538
  "group-status": {
92275
92539
  scope: "device",
92276
92540
  noun: t("Group", "Gruppo"),
@@ -92834,6 +93098,7 @@ var CAP_NAMES_WITH_STATUS = [
92834
93098
  "feature-probe",
92835
93099
  "flood",
92836
93100
  "gas",
93101
+ "group-commands",
92837
93102
  "group-status",
92838
93103
  "heating-valve",
92839
93104
  "humidifier",
@@ -92964,6 +93229,7 @@ var ALL_CAPABILITY_DEFINITIONS = [
92964
93229
  filesystemBrowseCapability,
92965
93230
  floodCapability,
92966
93231
  gasCapability,
93232
+ groupCommandsCapability,
92967
93233
  groupStatusCapability,
92968
93234
  heatingValveCapability,
92969
93235
  humidifierCapability,
@@ -94039,6 +94305,11 @@ Object.freeze({
94039
94305
  form: "single",
94040
94306
  optional: false
94041
94307
  }],
94308
+ "groupCommands.getStatus": [{
94309
+ name: "deviceId",
94310
+ form: "single",
94311
+ optional: false
94312
+ }],
94042
94313
  "groupStatus.getStatus": [{
94043
94314
  name: "deviceId",
94044
94315
  form: "single",
@@ -95853,7 +96124,7 @@ Object.freeze({
95853
96124
  });
95854
96125
  /**
95855
96126
  * Per-cap runtime-state policy, projected from every `*.cap.ts` that declares
95856
- * `runtimeState`. 73 caps: 38 `restored`, 35 `session`.
96127
+ * `runtimeState`. 74 caps: 38 `restored`, 36 `session`.
95857
96128
  *
95858
96129
  * A cap absent from this map has no runtime-state slice at all. A cap PRESENT
95859
96130
  * with `durability: 'session'` has one and has decided not to keep it.
@@ -95971,6 +96242,10 @@ var RUNTIME_STATE_POLICY = {
95971
96242
  durability: "restored",
95972
96243
  volatileFields: ["lastChangedAt"]
95973
96244
  },
96245
+ "group-commands": {
96246
+ durability: "session",
96247
+ volatileFields: []
96248
+ },
95974
96249
  "group-status": {
95975
96250
  durability: "session",
95976
96251
  volatileFields: []
@@ -96169,7 +96444,7 @@ var SESSION_ONLY_POLICY = {
96169
96444
  };
96170
96445
  /**
96171
96446
  * Cap history catalog, projected from every `*.cap.ts` `history` block.
96172
- * 41 caps with series (75 series), 31 caps answered `'none'`.
96447
+ * 41 caps with series (75 series), 32 caps answered `'none'`.
96173
96448
  * Field keys are `runtimeState` paths (`a.b` into fixed objects only).
96174
96449
  */
96175
96450
  var HISTORY_CATALOG = {
@@ -96741,6 +97016,8 @@ new Map(Object.entries({
96741
97016
  "detection-blind": "device-events",
96742
97017
  "motion-noisy": "device-events",
96743
97018
  "motion-calm": "device-events",
97019
+ "package-llm-silent": "device-events",
97020
+ "package-llm-answered": "device-events",
96744
97021
  "recording-stalled": "device-events",
96745
97022
  "recording-healthy": "device-events",
96746
97023
  "recording-degraded": "device-events",
@@ -96824,6 +97101,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
96824
97101
  label: "Motion without a subject",
96825
97102
  kinds: ["motion-noisy", "motion-calm"]
96826
97103
  },
97104
+ {
97105
+ id: "package-llm",
97106
+ family: "device-events",
97107
+ label: "Package confirm",
97108
+ kinds: ["package-llm-silent", "package-llm-answered"]
97109
+ },
96827
97110
  {
96828
97111
  id: "recording",
96829
97112
  family: "device-events",
@@ -97047,6 +97330,8 @@ var DEVICE_EVENTS = [
97047
97330
  "detection-blind",
97048
97331
  "motion-noisy",
97049
97332
  "motion-calm",
97333
+ "package-llm-silent",
97334
+ "package-llm-answered",
97050
97335
  "recording-stalled",
97051
97336
  "recording-healthy",
97052
97337
  "recording-degraded",
@@ -97315,6 +97600,15 @@ new Map([
97315
97600
  snapshotLabel: "Cameras with constant motion now",
97316
97601
  snapshotSection: null
97317
97602
  },
97603
+ {
97604
+ id: "package-llm-confirm",
97605
+ family: "device-events",
97606
+ label: "Package confirm (not answering / answering again)",
97607
+ bad: ["package-llm-silent"],
97608
+ recovery: ["package-llm-answered"],
97609
+ snapshotLabel: "Cameras whose package confirm is not answering",
97610
+ snapshotSection: null
97611
+ },
97318
97612
  {
97319
97613
  id: "recording-health",
97320
97614
  family: "device-events",
@@ -98600,6 +98894,12 @@ Object.defineProperty(exports, "ForeignSecretMarkerError", {
98600
98894
  return ForeignSecretMarkerError;
98601
98895
  }
98602
98896
  });
98897
+ Object.defineProperty(exports, "GroupCommandResultSchema", {
98898
+ enumerable: true,
98899
+ get: function() {
98900
+ return GroupCommandResultSchema;
98901
+ }
98902
+ });
98603
98903
  Object.defineProperty(exports, "HISTORY_CATALOG", {
98604
98904
  enumerable: true,
98605
98905
  get: function() {
@@ -99032,6 +99332,12 @@ Object.defineProperty(exports, "batteryCapability", {
99032
99332
  return batteryCapability;
99033
99333
  }
99034
99334
  });
99335
+ Object.defineProperty(exports, "brightnessCapability", {
99336
+ enumerable: true,
99337
+ get: function() {
99338
+ return brightnessCapability;
99339
+ }
99340
+ });
99035
99341
  Object.defineProperty(exports, "buildCapabilityLookup", {
99036
99342
  enumerable: true,
99037
99343
  get: function() {
@@ -99122,6 +99428,12 @@ Object.defineProperty(exports, "collectZodSecretPaths", {
99122
99428
  return collectZodSecretPaths;
99123
99429
  }
99124
99430
  });
99431
+ Object.defineProperty(exports, "colorCapability", {
99432
+ enumerable: true,
99433
+ get: function() {
99434
+ return colorCapability;
99435
+ }
99436
+ });
99125
99437
  Object.defineProperty(exports, "composedDeviceRef", {
99126
99438
  enumerable: true,
99127
99439
  get: function() {
@@ -99404,6 +99716,12 @@ Object.defineProperty(exports, "extractNestedAddonId", {
99404
99716
  return extractNestedAddonId;
99405
99717
  }
99406
99718
  });
99719
+ Object.defineProperty(exports, "fanOutTargets", {
99720
+ enumerable: true,
99721
+ get: function() {
99722
+ return fanOutTargets;
99723
+ }
99724
+ });
99407
99725
  Object.defineProperty(exports, "filesystemBrowseCapability", {
99408
99726
  enumerable: true,
99409
99727
  get: function() {
@@ -99440,6 +99758,18 @@ Object.defineProperty(exports, "gbToBytes", {
99440
99758
  return gbToBytes;
99441
99759
  }
99442
99760
  });
99761
+ Object.defineProperty(exports, "groupCommandsCapability", {
99762
+ enumerable: true,
99763
+ get: function() {
99764
+ return groupCommandsCapability;
99765
+ }
99766
+ });
99767
+ Object.defineProperty(exports, "groupTemplate", {
99768
+ enumerable: true,
99769
+ get: function() {
99770
+ return groupTemplate;
99771
+ }
99772
+ });
99443
99773
  Object.defineProperty(exports, "historyItemFieldPath", {
99444
99774
  enumerable: true,
99445
99775
  get: function() {
@@ -99734,6 +100064,12 @@ Object.defineProperty(exports, "parseAcceleratorFactsJson", {
99734
100064
  return parseAcceleratorFactsJson;
99735
100065
  }
99736
100066
  });
100067
+ Object.defineProperty(exports, "parseColorInput", {
100068
+ enumerable: true,
100069
+ get: function() {
100070
+ return parseColorInput;
100071
+ }
100072
+ });
99737
100073
  Object.defineProperty(exports, "parseJsonObject", {
99738
100074
  enumerable: true,
99739
100075
  get: function() {
@@ -99890,6 +100226,12 @@ Object.defineProperty(exports, "resolveSecretMarkers", {
99890
100226
  return resolveSecretMarkers;
99891
100227
  }
99892
100228
  });
100229
+ Object.defineProperty(exports, "runFanOut", {
100230
+ enumerable: true,
100231
+ get: function() {
100232
+ return runFanOut;
100233
+ }
100234
+ });
99893
100235
  Object.defineProperty(exports, "runtimeStatePolicyFor", {
99894
100236
  enumerable: true,
99895
100237
  get: function() {
@@ -99938,6 +100280,18 @@ Object.defineProperty(exports, "settingsStoreCapability", {
99938
100280
  return settingsStoreCapability;
99939
100281
  }
99940
100282
  });
100283
+ Object.defineProperty(exports, "sharedColorModes", {
100284
+ enumerable: true,
100285
+ get: function() {
100286
+ return sharedColorModes;
100287
+ }
100288
+ });
100289
+ Object.defineProperty(exports, "sharedLightCaps", {
100290
+ enumerable: true,
100291
+ get: function() {
100292
+ return sharedLightCaps;
100293
+ }
100294
+ });
99941
100295
  Object.defineProperty(exports, "shortHostname", {
99942
100296
  enumerable: true,
99943
100297
  get: function() {
@@ -100016,6 +100370,12 @@ Object.defineProperty(exports, "supportedRuntimes", {
100016
100370
  return supportedRuntimes;
100017
100371
  }
100018
100372
  });
100373
+ Object.defineProperty(exports, "switchCapability", {
100374
+ enumerable: true,
100375
+ get: function() {
100376
+ return switchCapability;
100377
+ }
100378
+ });
100019
100379
  Object.defineProperty(exports, "toExpressionValue", {
100020
100380
  enumerable: true,
100021
100381
  get: function() {