@camstack/addon-provider-velux 0.2.131 → 0.2.133

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 (3) hide show
  1. package/dist/addon.js +348 -41
  2. package/dist/addon.mjs +348 -41
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -5414,7 +5414,7 @@ var ZodIssueCode = {
5414
5414
  var ZodFirstPartyTypeKind;
5415
5415
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5416
5416
  //#endregion
5417
- //#region ../types/dist/sleep-yKL5gfrH.mjs
5417
+ //#region ../types/dist/sleep-BSuCCFjf.mjs
5418
5418
  /**
5419
5419
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5420
5420
  * window to float samples (D455).
@@ -17008,7 +17008,19 @@ var DeviceHistorySubjectSchema = discriminatedUnion("kind", [object({
17008
17008
  kind: literal("node"),
17009
17009
  nodeId: string().min(1)
17010
17010
  })]);
17011
+ /**
17012
+ * `enum` stores a STATE as the ordinal of its value in the series' value list
17013
+ * (`DeviceHistorySeriesInfo.values`, append-only, so an ordinal never changes
17014
+ * meaning); a rollup keeps the time spent in each state (`states`).
17015
+ */
17011
17016
  var DeviceHistoryKindSchema = _enum([
17017
+ "gauge",
17018
+ "counter",
17019
+ "boolean",
17020
+ "enum"
17021
+ ]);
17022
+ /** What a PRODUCER may declare. `enum` is cap-only: its value list is the cap field's. */
17023
+ var DeviceHistoryProducerKindSchema = _enum([
17012
17024
  "gauge",
17013
17025
  "counter",
17014
17026
  "boolean"
@@ -17045,7 +17057,13 @@ var SeriesInfoSchema = object({
17045
17057
  /** `null` is unknown (a `unitFrom` series whose device does not state a unit right now), never a guess. */
17046
17058
  unit: string().nullable(),
17047
17059
  displayName: string(),
17048
- source: _enum(["cap", "addon"]),
17060
+ source: _enum([
17061
+ "cap",
17062
+ "addon",
17063
+ "derived"
17064
+ ]),
17065
+ /** `enum`: the value of each ordinal (index = ordinal); `null` for every other kind. */
17066
+ values: array(string()).readonly().nullable(),
17049
17067
  firstTs: number(),
17050
17068
  lastTs: number()
17051
17069
  });
@@ -17059,17 +17077,31 @@ var QueryPointSchema = object({
17059
17077
  twMean: number().nullable(),
17060
17078
  min: number(),
17061
17079
  max: number(),
17062
- /** `null` is unknown, never zero (D393). */
17063
- last: number().nullable()
17080
+ /** `null` is unknown, never zero (D393). For an `enum` series: the ordinal of {@link state}. */
17081
+ last: number().nullable(),
17082
+ /**
17083
+ * The increase over the point: a `counter`'s growth since the previous point
17084
+ * or bucket (a drop is a reset, counted from zero), and for
17085
+ * {@link DEVICE_HISTORY_ENERGY_KEY} the kWh used in the bucket. `null` for
17086
+ * every other kind, and when it cannot be known.
17087
+ */
17088
+ delta: number().nullable(),
17089
+ /** `enum`: the state in force at the end of the point (the name of `last`); `null` otherwise. */
17090
+ state: string().nullable(),
17091
+ /** `enum` rollup: milliseconds spent in each state inside the bucket; `null` for raw points and other kinds. */
17092
+ states: record(string(), number()).nullable()
17064
17093
  });
17065
17094
  var QuerySeriesSchema = object({
17066
17095
  scope: string(),
17067
17096
  /** The last point STRICTLY BEFORE `from` in the chosen tier, so a step chart can start at the held value. */
17068
17097
  before: object({
17069
17098
  t: number(),
17070
- value: number().nullable()
17099
+ value: number().nullable(),
17100
+ state: string().nullable()
17071
17101
  }).nullable(),
17072
- points: array(QueryPointSchema).readonly()
17102
+ points: array(QueryPointSchema).readonly(),
17103
+ /** A derived key: the stored key its points were computed from; `null` for a stored series. */
17104
+ derivedFrom: string().nullable()
17073
17105
  });
17074
17106
  /** The window part of a query, shared by the device and node forms. */
17075
17107
  var QueryWindowShape = {
@@ -17085,6 +17117,23 @@ var QueryResultSchema = object({
17085
17117
  series: array(QuerySeriesSchema).readonly(),
17086
17118
  truncated: boolean()
17087
17119
  });
17120
+ /** One read of a batch: a device's key or a node's key (exactly one subject). */
17121
+ var QueryManyItemSchema = union([object({
17122
+ deviceId: number().int(),
17123
+ key: string(),
17124
+ scope: string().optional()
17125
+ }), object({
17126
+ forNodeId: string().min(1),
17127
+ key: string(),
17128
+ scope: string().optional()
17129
+ })]);
17130
+ var QueryManyEntrySchema = discriminatedUnion("ok", [object({
17131
+ ok: literal(true),
17132
+ result: QueryResultSchema
17133
+ }), object({
17134
+ ok: literal(false),
17135
+ error: string()
17136
+ })]);
17088
17137
  var TierStatusSchema = object({
17089
17138
  tier: DeviceHistoryResolutionSchema,
17090
17139
  /** `null` until the first background count answered. */
@@ -17140,16 +17189,22 @@ var DeviceHistoryStatusSchema = object({
17140
17189
  lastRefreshAt: number().nullable()
17141
17190
  })
17142
17191
  });
17143
- method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly()), method(object({ nodeId: string().min(1) }), array(SeriesInfoSchema).readonly(), { auth: "admin" }), method(object({
17192
+ method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly()), method(object({ forNodeId: string().min(1) }), array(SeriesInfoSchema).readonly(), { auth: "admin" }), method(object({
17144
17193
  deviceId: number().int(),
17145
17194
  ...QueryWindowShape
17146
17195
  }), QueryResultSchema), method(object({
17147
- nodeId: string().min(1),
17196
+ forNodeId: string().min(1),
17148
17197
  ...QueryWindowShape
17149
17198
  }), QueryResultSchema, { auth: "admin" }), method(object({
17199
+ items: array(QueryManyItemSchema).min(1).max(24),
17200
+ from: QueryWindowShape.from,
17201
+ to: QueryWindowShape.to,
17202
+ resolution: QueryWindowShape.resolution,
17203
+ maxPoints: QueryWindowShape.maxPoints
17204
+ }), object({ results: array(QueryManyEntrySchema).readonly() }), { auth: "admin" }), method(object({
17150
17205
  name: string().regex(/^[a-z0-9-]+$/),
17151
17206
  subjectKind: _enum(["device", "node"]),
17152
- kind: DeviceHistoryKindSchema,
17207
+ kind: DeviceHistoryProducerKindSchema,
17153
17208
  unit: string().optional(),
17154
17209
  displayName: string().min(1),
17155
17210
  ingest: _enum(["points", "buckets"])
@@ -40471,14 +40526,106 @@ var LogEntrySchema = object({
40471
40526
  meta: record(string(), unknown()).optional(),
40472
40527
  tags: record(string(), string()).optional()
40473
40528
  });
40474
- method(LogEntrySchema, _void(), { kind: "mutation" }), method(object({
40475
- scope: array(string()).optional(),
40529
+ /**
40530
+ * A history READ against one destination (D898).
40531
+ *
40532
+ * Every filter is applied by the PROVIDER, before the limit — a filter the
40533
+ * browser applied after the limit is what made a rare device's lines
40534
+ * unreachable behind a busy one's. `before` / `after` are cursors the provider
40535
+ * minted (opaque to everyone else): a file position for the rotated files, a
40536
+ * nanosecond timestamp for Loki.
40537
+ *
40538
+ * A read is BOUNDED by `budgetMs`: a filter that matches nothing on a 30-day
40539
+ * store answers `done: false` with the cursor it reached and the bytes it
40540
+ * scanned, and the caller decides whether to go on. That is what makes a long
40541
+ * scan show progress and stop when asked — `cancelRead` ends the slice in
40542
+ * flight, and not asking for the next slice ends the scan.
40543
+ */
40544
+ var LogReadQuerySchema = object({
40545
+ /** Correlates `cancelRead`. Caller-chosen, unique per in-flight read. */
40546
+ requestId: string().min(1).max(64).optional(),
40547
+ /** The device the line is about (`tags.deviceId`, numeric). */
40548
+ deviceId: number().int().optional(),
40549
+ /**
40550
+ * The emitting addon — bare manifest id; `@<version>` / `::<sub>` suffixes
40551
+ * match. Not `addonId`: a cap router reads that name as "which provider".
40552
+ */
40553
+ fromAddonId: string().min(1).max(200).optional(),
40554
+ /**
40555
+ * The emitting node: matches the agent that emitted the line, the node
40556
+ * itself, or a worker under it (`<agent>/<runner>`) — the `agentId`
40557
+ * semantics of `matchesLogTags`. Not `nodeId`: a cap router reads that
40558
+ * name as "which node's provider".
40559
+ */
40560
+ fromNodeId: string().min(1).max(200).optional(),
40561
+ /** Any other tag, exact match (AND). */
40562
+ tags: record(string(), union([string(), number()])).optional(),
40563
+ /** Severity FLOOR: this level and above. */
40476
40564
  level: LogLevelSchema.optional(),
40477
- since: date().optional(),
40478
- until: date().optional(),
40479
- limit: number().optional(),
40480
- tags: record(string(), string()).optional()
40481
- }), array(LogEntrySchema).readonly());
40565
+ /** Case-insensitive substring over message, scope, tag values and meta values. */
40566
+ text: string().min(1).max(200).optional(),
40567
+ /** Epoch ms, inclusive. */
40568
+ since: number().optional(),
40569
+ /** Epoch ms, inclusive. */
40570
+ until: number().optional(),
40571
+ /** Older than this cursor (exclusive). Absent with `after` absent ⇒ from the newest. */
40572
+ before: string().min(1).max(1024).optional(),
40573
+ /** Newer than this cursor (exclusive). */
40574
+ after: string().min(1).max(1024).optional(),
40575
+ limit: number().int().min(1).max(1e3).optional(),
40576
+ /** Wall-clock bound of this slice. The provider caps it. */
40577
+ budgetMs: number().int().min(50).max(1e4).optional()
40578
+ });
40579
+ var LogReadResultSchema = object({
40580
+ /** Newest first. */
40581
+ entries: array(object({
40582
+ /** `<bootId>.<seq>` minted by the emitting LogManager — the dedupe key. */
40583
+ id: string().optional(),
40584
+ /** Epoch ms. */
40585
+ timestamp: number(),
40586
+ level: LogLevelSchema,
40587
+ scope: string().optional(),
40588
+ message: string(),
40589
+ tags: record(string(), union([string(), number()])).optional(),
40590
+ meta: record(string(), unknown()).optional()
40591
+ })),
40592
+ /** Pass as `before` for the next older page; null when nothing older exists. */
40593
+ nextBefore: string().nullable(),
40594
+ /** Pass as `after` to read what arrived since; null when unknown. */
40595
+ nextAfter: string().nullable(),
40596
+ /** Bytes this slice read (files) or received (remote). Progress, not a promise. */
40597
+ scannedBytes: number().int().nonnegative(),
40598
+ /**
40599
+ * True when the scan in this direction reached the end of the store.
40600
+ * False with fewer than `limit` entries means the budget ran out first —
40601
+ * call again with `nextBefore` to go on.
40602
+ */
40603
+ done: boolean(),
40604
+ /** True when `cancelRead` ended this slice early. */
40605
+ cancelled: boolean().optional()
40606
+ });
40607
+ var LogReadCapabilitiesSchema = object({
40608
+ /** False ⇒ this destination only ships lines (console, forwarder, an unconfigured Loki). */
40609
+ readable: boolean(),
40610
+ /** Why not, when `readable` is false — rendered next to the source. */
40611
+ reason: string().nullable(),
40612
+ /** Filters the provider applies itself. A false one is applied by nobody. */
40613
+ filters: object({
40614
+ deviceId: boolean(),
40615
+ addonId: boolean(),
40616
+ nodeId: boolean(),
40617
+ tags: boolean(),
40618
+ level: boolean(),
40619
+ text: boolean(),
40620
+ timeRange: boolean()
40621
+ }),
40622
+ /** How far back the store reaches, when the provider knows (days). */
40623
+ retentionDays: number().nullable()
40624
+ });
40625
+ method(LogEntrySchema, _void(), { kind: "mutation" }), optionalMethod(_void(), LogReadCapabilitiesSchema, { auth: "admin" }), optionalMethod(LogReadQuerySchema, LogReadResultSchema, { auth: "admin" }), optionalMethod(object({ requestId: string().min(1).max(64) }), object({ cancelled: boolean() }), {
40626
+ kind: "mutation",
40627
+ auth: "admin"
40628
+ });
40482
40629
  /**
40483
40630
  * `login-method` — collection cap through which auth addons contribute
40484
40631
  * their pre-auth login surfaces to the login page. This is the SINGLE,
@@ -42196,9 +42343,11 @@ var alarmPanelCapability = {
42196
42343
  */
42197
42344
  durability: "restored",
42198
42345
  /**
42199
- * History (D850): none — enum state; arm/disarm history belongs in the events ledger.
42346
+ * History (D850): the panel's lifecycle state as an `enum` series —
42347
+ * change-only, no floor, so an `arming -> pending -> triggered` sequence of a
42348
+ * few seconds keeps every step. Who armed it stays in the events ledger.
42200
42349
  */
42201
- history: "none",
42350
+ history: { fields: { state: { kind: "enum" } } },
42202
42351
  /** Clock fields: written, but excluded from the compare that decides
42203
42352
  * whether persisting is worth a SQLite commit. */
42204
42353
  volatileStateFields: ["lastChangedAt"]
@@ -43076,6 +43225,33 @@ var NcRuleTargetSchema = object({
43076
43225
  params: record(string(), unknown()).optional()
43077
43226
  });
43078
43227
  /**
43228
+ * WHAT THE NOTIFICATION'S PICTURE IS (D897) — the ONE media choice of a rule.
43229
+ *
43230
+ * Every mode starts from the same CLEAN source frame of the trigger moment
43231
+ * (keyFrame → sceneFrame → lastSceneFrame, narrowed to the trigger instant and
43232
+ * to the zone that fired the rule) and renders it once at send time:
43233
+ * - `scene-boxes` — the whole scene, the subject outlined thick in the accent
43234
+ * colour and every OTHER track visible at that instant outlined thin, each
43235
+ * labelled with class and confidence ("dog 87%").
43236
+ * - `crop` — the subject cut out of that frame around its box at that instant.
43237
+ * - `clean` — the whole scene with nothing drawn on it.
43238
+ * - `none` — no picture.
43239
+ *
43240
+ * A mode that cannot be honoured (no box at that instant, a photograph with no
43241
+ * tracked subject) ships `clean` and names the reason in the log, per camera.
43242
+ * It replaces the `attach` × `frame` × `zoneCrop` triple, which let one rule
43243
+ * ship a crop on one event and a boxed scene on the next depending on which
43244
+ * stored kind had landed.
43245
+ */
43246
+ var NcMediaImageSchema = _enum([
43247
+ "scene-boxes",
43248
+ "crop",
43249
+ "clean",
43250
+ "none"
43251
+ ]);
43252
+ /**
43253
+ * @deprecated Read only by `normalizeNcMediaPolicy` (D897) — see {@link NcMediaImageSchema}.
43254
+ *
43079
43255
  * Media attachment policy (P1 still-image subset).
43080
43256
  * - `best` — the best AVAILABLE subject image at dispatch time (D-3).
43081
43257
  * - `best-matching` — the media that explains WHY the rule fired: a rule
@@ -43089,6 +43265,8 @@ var NcRuleTargetSchema = object({
43089
43265
  * - `none` — no attachment.
43090
43266
  */
43091
43267
  /**
43268
+ * @deprecated Read only by `normalizeNcMediaPolicy` (D897) — see {@link NcMediaImageSchema}.
43269
+ *
43092
43270
  * WHAT THE PICTURE SHOWS — chosen explicitly, because the implicit ladders
43093
43271
  * conflate it with the selection strategy and betray the request: asking for
43094
43272
  * the clean scene frame on an object-event owner used to start at
@@ -43117,16 +43295,29 @@ var NcMediaFrameSchema = _enum([
43117
43295
  */
43118
43296
  var NcLinkedCameraModeSchema = _enum(["mosaic", "each"]);
43119
43297
  var NcMediaPolicySchema = object({
43298
+ /**
43299
+ * The picture — see {@link NcMediaImageSchema}. Absent on a rule nobody has
43300
+ * saved since D897: `normalizeNcMediaPolicy` derives it from the legacy
43301
+ * triple below, at load and at every write, and the store keeps only this.
43302
+ */
43303
+ image: NcMediaImageSchema.optional(),
43304
+ /**
43305
+ * Draw the zone that FIRED the rule on the picture (`scene-boxes` / `clean`;
43306
+ * a `crop` never shows it). Valid only on a rule whose trigger is a zone —
43307
+ * `conditions.zones` or an occupancy zone — and refused on save otherwise.
43308
+ * Replaces `zoneCrop`.
43309
+ */
43310
+ showTriggerZone: boolean().optional(),
43311
+ /** @deprecated D897 — accepted from an editor that predates `image`, folded into it on save. */
43120
43312
  attach: _enum([
43121
43313
  "best",
43122
43314
  "best-matching",
43123
43315
  "keyFrame",
43124
43316
  "none"
43125
- ]).default("best"),
43126
- /** What the still shows. Absent = `cropped` (the historical `best` shape). */
43317
+ ]).optional(),
43318
+ /** @deprecated D897 — accepted from an editor that predates `image`, folded into it on save. */
43127
43319
  frame: NcMediaFrameSchema.optional(),
43128
- /** Crop the attached still to the rule's condition-zone bbox (padded) —
43129
- * "show me the ZONE", not the whole scene or the subject crop. */
43320
+ /** @deprecated D897 — folded into `image: 'clean'` + `showTriggerZone` on save. */
43130
43321
  zoneCrop: boolean().optional(),
43131
43322
  /**
43132
43323
  * Also attach a short GIF cut from the stream broker's clip ring around the
@@ -43298,7 +43489,9 @@ var NcRuleInputSchema = object({
43298
43489
  * targets.
43299
43490
  */
43300
43491
  targetUsers: array(string()).optional(),
43301
- media: NcMediaPolicySchema.default({ attach: "best" }),
43492
+ /** Absent = the kind's default picture (`resolveNcMediaImage`): the subject crop for a
43493
+ * detection, the clean scene for a sensor or a sound. Set explicitly on save (D897). */
43494
+ media: NcMediaPolicySchema.default({}),
43302
43495
  throttle: NcThrottleSchema.default({
43303
43496
  cooldownSec: 60,
43304
43497
  scope: "rule-device"
@@ -44235,13 +44428,37 @@ var NcAlarmModeOpeningsSchema = object({
44235
44428
  /** Covered devices whose state could not be read (D49): neither open nor closed. */
44236
44429
  unknown: array(number().int())
44237
44430
  });
44431
+ /**
44432
+ * One alarm INPUT — a (rule, device) pair — the operator bypassed until the
44433
+ * next disarm ("Bypass this input until disarm" on a trigger notification, or
44434
+ * `nc.bypassAlarmInput`). Reported so an armed alarm with a silenced input
44435
+ * never looks fully armed (D62: off must never look like broken).
44436
+ */
44437
+ var NcAlarmInputBypassViewSchema = object({
44438
+ ruleId: string(),
44439
+ /** The rule's current name (its frozen name when the rule is gone). */
44440
+ ruleName: string(),
44441
+ /** The input: the sensor of the match, else its camera. */
44442
+ deviceId: number().int(),
44443
+ /** The input's current name. */
44444
+ name: string(),
44445
+ /** When it was bypassed (ms epoch). */
44446
+ since: number(),
44447
+ /** Triggers from this input dropped since. */
44448
+ dropped: number().int().min(0)
44449
+ });
44238
44450
  var NcAlarmLiveSchema = object({
44239
44451
  state: AlarmStateSchema,
44240
44452
  /** The mode being armed into (exit delay) or held; null when disarmed. */
44241
44453
  targetMode: AlarmArmModeSchema.nullable(),
44242
44454
  availableModes: array(AlarmArmModeSchema),
44243
44455
  openings: array(NcAlarmModeOpeningsSchema),
44244
- exclusions: array(NcAlarmExclusionViewSchema)
44456
+ exclusions: array(NcAlarmExclusionViewSchema),
44457
+ /**
44458
+ * Inputs bypassed for the rest of this arm session; cleared on disarm.
44459
+ * Defaulted so an older hub answer still parses (as "none known").
44460
+ */
44461
+ bypassedInputs: array(NcAlarmInputBypassViewSchema).default([])
44245
44462
  });
44246
44463
  var NcAlarmConfigSchema = object({
44247
44464
  /**
@@ -54960,9 +55177,11 @@ var connectivityCapability = {
54960
55177
  */
54961
55178
  durability: "restored",
54962
55179
  /**
54963
- * History (D850): none — duplicates device-status.online (one authority for availability).
55180
+ * History (D850): `connected` as a boolean series — change-only, no floor. It
55181
+ * is the upstream entity's own link (a HA connectivity sensor), not the
55182
+ * device's reachability, which stays `device-status.online`.
54964
55183
  */
54965
- history: "none",
55184
+ history: { fields: { connected: { kind: "boolean" } } },
54966
55185
  /** Clock fields: written, but excluded from the compare that decides
54967
55186
  * whether persisting is worth a SQLite commit. */
54968
55187
  volatileStateFields: ["lastChangedAt"]
@@ -55786,11 +56005,22 @@ var dishwasherCapability = {
55786
56005
  },
55787
56006
  runtimeState: DishwasherStatusSchema,
55788
56007
  durability: "session",
55789
- history: { fields: { progressPercent: {
55790
- kind: "gauge",
55791
- unit: "%",
55792
- deadband: 2
55793
- } } }
56008
+ history: { fields: {
56009
+ progressPercent: {
56010
+ kind: "gauge",
56011
+ unit: "%",
56012
+ deadband: 2
56013
+ },
56014
+ state: { kind: "enum" },
56015
+ operationState: { kind: "enum" },
56016
+ remainingSeconds: {
56017
+ kind: "gauge",
56018
+ unit: "s",
56019
+ minIntervalMs: 6e4
56020
+ },
56021
+ doorOpen: { kind: "boolean" },
56022
+ powerOn: { kind: "boolean" }
56023
+ } }
55794
56024
  };
55795
56025
  var DoorbellStatusSchema = object({
55796
56026
  /** Ms epoch of the last press. null = never observed since this provider started. */
@@ -55907,9 +56137,15 @@ var enumSensorCapability = {
55907
56137
  */
55908
56138
  durability: "restored",
55909
56139
  /**
55910
- * History (D850): none — text/enum state has no history (non-goal).
56140
+ * History (D850): the value as an `enum` series (an appliance's program or
56141
+ * operation state, an HVAC action). The option set is per device, so the
56142
+ * value list is LEARNED as values are first seen (bounded). A sensor with a
56143
+ * `format` carries a timestamp, not a state, and is not recorded.
55911
56144
  */
55912
- history: "none",
56145
+ history: { fields: { value: {
56146
+ kind: "enum",
56147
+ skipWhenSet: "format"
56148
+ } } },
55913
56149
  /** Clock fields: written, but excluded from the compare that decides
55914
56150
  * whether persisting is worth a SQLite commit. */
55915
56151
  volatileStateFields: ["lastFetchedAt"]
@@ -57883,9 +58119,10 @@ var lockControlCapability = {
57883
58119
  */
57884
58120
  durability: "restored",
57885
58121
  /**
57886
- * History (D850): none — enum state; lock events belong in the events ledger.
58122
+ * History (D850): the lock's state as an `enum` series — change-only, no
58123
+ * floor: a jam or an unlock lasting seconds is the edge an operator looks for.
57887
58124
  */
57888
- history: "none",
58125
+ history: { fields: { state: { kind: "enum" } } },
57889
58126
  /** Clock fields: written, but excluded from the compare that decides
57890
58127
  * whether persisting is worth a SQLite commit. */
57891
58128
  volatileStateFields: ["lastChangedAt"]
@@ -58059,9 +58296,18 @@ var mediaPlayerCapability = {
58059
58296
  */
58060
58297
  durability: "session",
58061
58298
  /**
58062
- * History (D850): none — `positionMs` moves continuously while playing; volume is transient.
58299
+ * History (D850): volume (a level an operator or an automation sets; the
58300
+ * default 10 s floor folds a slider drag into its end value) and mute.
58301
+ * `positionMs` is not recorded: it moves continuously while playing.
58063
58302
  */
58064
- history: "none"
58303
+ history: { fields: {
58304
+ volumeLevel: {
58305
+ kind: "gauge",
58306
+ unit: "%",
58307
+ deadband: 1
58308
+ },
58309
+ isMuted: { kind: "boolean" }
58310
+ } }
58065
58311
  };
58066
58312
  /**
58067
58313
  * mesh-network — collection cap for mesh-VPN providers.
@@ -60205,9 +60451,24 @@ var NpuInfoSchema = object({
60205
60451
  name: string().optional(),
60206
60452
  generation: _enum(["xdna1", "xdna2"]).optional()
60207
60453
  });
60454
+ var CoralBusSchema = _enum(["usb", "pci"]);
60208
60455
  var CoralInfoSchema = object({
60209
60456
  type: literal("coral-edgetpu"),
60210
- bus: string().optional()
60457
+ /** Legacy single-bus report (older nodes) — read via `coralUsableUnits`. */
60458
+ bus: string().optional(),
60459
+ /** Legacy USB unit count (older nodes) — read via `coralUsableUnits`. */
60460
+ count: number().int().nonnegative().optional(),
60461
+ /** Usable units per bus — each one is its own `edgetpu:<bus>[:N]` device. */
60462
+ units: array(object({
60463
+ bus: CoralBusSchema,
60464
+ count: number().int().nonnegative()
60465
+ })).readonly().optional(),
60466
+ /** Present-but-unusable units, each with its typed reason (never "absent"). */
60467
+ unavailable: array(object({
60468
+ bus: CoralBusSchema,
60469
+ count: number().int().nonnegative(),
60470
+ reason: _enum(["driver-missing", "device-not-accessible"])
60471
+ })).readonly().optional()
60211
60472
  });
60212
60473
  var HardwareInfoSchema = object({
60213
60474
  platform: HardwarePlatformSchema,
@@ -63354,9 +63615,29 @@ var streamParamsCapability = {
63354
63615
  */
63355
63616
  durability: "restored",
63356
63617
  /**
63357
- * History (D850): none — encoder configuration.
63618
+ * History (D850): the configured bitrate and frame rate of the main and sub
63619
+ * profiles. Configuration, so change-only on the default floor: a point is an
63620
+ * operator's (or a tuner's) edit, which is exactly what a chart of a stream's
63621
+ * quality over time must show.
63358
63622
  */
63359
- history: "none",
63623
+ history: { fields: {
63624
+ "main.bitrate": {
63625
+ kind: "gauge",
63626
+ unit: "kbps"
63627
+ },
63628
+ "main.framerate": {
63629
+ kind: "gauge",
63630
+ unit: "fps"
63631
+ },
63632
+ "sub.bitrate": {
63633
+ kind: "gauge",
63634
+ unit: "kbps"
63635
+ },
63636
+ "sub.framerate": {
63637
+ kind: "gauge",
63638
+ unit: "fps"
63639
+ }
63640
+ } },
63360
63641
  /** Clock fields: written, but excluded from the compare that decides
63361
63642
  * whether persisting is worth a SQLite commit. */
63362
63643
  volatileStateFields: ["lastFetchedAt"]
@@ -66534,6 +66815,15 @@ var BaseDevice = class {
66534
66815
  * Drivers can use the `getProbeFlags()` helper to read the flag bag
66535
66816
  * with a typed cast.
66536
66817
  *
66818
+ * Answer what you KNOW. A plain array is read as the complete list only
66819
+ * while this device is `online` and probed; return
66820
+ * `accessoryChildrenUnknown(reason)` whenever you cannot know the list right
66821
+ * now (no credentials, parent not connected, a failed or partial read) —
66822
+ * the kernel then deletes nothing. Return `accessoryChildrenComplete(list)`
66823
+ * to say "connected, and this is the complete list" explicitly. A shrink is
66824
+ * deleted only after a second agreeing complete read on a later probe (D49;
66825
+ * `packages/system/src/kernel/moleculer/accessory-prune-gate.ts`).
66826
+ *
66537
66827
  * Default: no children.
66538
66828
  */
66539
66829
  getAccessoryChildren() {
@@ -70665,7 +70955,19 @@ Object.freeze({
70665
70955
  addonId: null,
70666
70956
  access: "view"
70667
70957
  },
70668
- "logDestination.query": {
70958
+ "logDestination.cancelRead": {
70959
+ capName: "log-destination",
70960
+ capScope: "system",
70961
+ addonId: null,
70962
+ access: "create"
70963
+ },
70964
+ "logDestination.describeRead": {
70965
+ capName: "log-destination",
70966
+ capScope: "system",
70967
+ addonId: null,
70968
+ access: "view"
70969
+ },
70970
+ "logDestination.read": {
70669
70971
  capName: "log-destination",
70670
70972
  capScope: "system",
70671
70973
  addonId: null,
@@ -76672,6 +76974,11 @@ Object.freeze({
76672
76974
  form: "single",
76673
76975
  optional: false
76674
76976
  }],
76977
+ "logDestination.read": [{
76978
+ name: "deviceId",
76979
+ form: "single",
76980
+ optional: true
76981
+ }],
76675
76982
  "mediaPlayer.getStatus": [{
76676
76983
  name: "deviceId",
76677
76984
  form: "single",
package/dist/addon.mjs CHANGED
@@ -5413,7 +5413,7 @@ var ZodIssueCode = {
5413
5413
  var ZodFirstPartyTypeKind;
5414
5414
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5415
5415
  //#endregion
5416
- //#region ../types/dist/sleep-yKL5gfrH.mjs
5416
+ //#region ../types/dist/sleep-BSuCCFjf.mjs
5417
5417
  /**
5418
5418
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5419
5419
  * window to float samples (D455).
@@ -17007,7 +17007,19 @@ var DeviceHistorySubjectSchema = discriminatedUnion("kind", [object({
17007
17007
  kind: literal("node"),
17008
17008
  nodeId: string().min(1)
17009
17009
  })]);
17010
+ /**
17011
+ * `enum` stores a STATE as the ordinal of its value in the series' value list
17012
+ * (`DeviceHistorySeriesInfo.values`, append-only, so an ordinal never changes
17013
+ * meaning); a rollup keeps the time spent in each state (`states`).
17014
+ */
17010
17015
  var DeviceHistoryKindSchema = _enum([
17016
+ "gauge",
17017
+ "counter",
17018
+ "boolean",
17019
+ "enum"
17020
+ ]);
17021
+ /** What a PRODUCER may declare. `enum` is cap-only: its value list is the cap field's. */
17022
+ var DeviceHistoryProducerKindSchema = _enum([
17011
17023
  "gauge",
17012
17024
  "counter",
17013
17025
  "boolean"
@@ -17044,7 +17056,13 @@ var SeriesInfoSchema = object({
17044
17056
  /** `null` is unknown (a `unitFrom` series whose device does not state a unit right now), never a guess. */
17045
17057
  unit: string().nullable(),
17046
17058
  displayName: string(),
17047
- source: _enum(["cap", "addon"]),
17059
+ source: _enum([
17060
+ "cap",
17061
+ "addon",
17062
+ "derived"
17063
+ ]),
17064
+ /** `enum`: the value of each ordinal (index = ordinal); `null` for every other kind. */
17065
+ values: array(string()).readonly().nullable(),
17048
17066
  firstTs: number(),
17049
17067
  lastTs: number()
17050
17068
  });
@@ -17058,17 +17076,31 @@ var QueryPointSchema = object({
17058
17076
  twMean: number().nullable(),
17059
17077
  min: number(),
17060
17078
  max: number(),
17061
- /** `null` is unknown, never zero (D393). */
17062
- last: number().nullable()
17079
+ /** `null` is unknown, never zero (D393). For an `enum` series: the ordinal of {@link state}. */
17080
+ last: number().nullable(),
17081
+ /**
17082
+ * The increase over the point: a `counter`'s growth since the previous point
17083
+ * or bucket (a drop is a reset, counted from zero), and for
17084
+ * {@link DEVICE_HISTORY_ENERGY_KEY} the kWh used in the bucket. `null` for
17085
+ * every other kind, and when it cannot be known.
17086
+ */
17087
+ delta: number().nullable(),
17088
+ /** `enum`: the state in force at the end of the point (the name of `last`); `null` otherwise. */
17089
+ state: string().nullable(),
17090
+ /** `enum` rollup: milliseconds spent in each state inside the bucket; `null` for raw points and other kinds. */
17091
+ states: record(string(), number()).nullable()
17063
17092
  });
17064
17093
  var QuerySeriesSchema = object({
17065
17094
  scope: string(),
17066
17095
  /** The last point STRICTLY BEFORE `from` in the chosen tier, so a step chart can start at the held value. */
17067
17096
  before: object({
17068
17097
  t: number(),
17069
- value: number().nullable()
17098
+ value: number().nullable(),
17099
+ state: string().nullable()
17070
17100
  }).nullable(),
17071
- points: array(QueryPointSchema).readonly()
17101
+ points: array(QueryPointSchema).readonly(),
17102
+ /** A derived key: the stored key its points were computed from; `null` for a stored series. */
17103
+ derivedFrom: string().nullable()
17072
17104
  });
17073
17105
  /** The window part of a query, shared by the device and node forms. */
17074
17106
  var QueryWindowShape = {
@@ -17084,6 +17116,23 @@ var QueryResultSchema = object({
17084
17116
  series: array(QuerySeriesSchema).readonly(),
17085
17117
  truncated: boolean()
17086
17118
  });
17119
+ /** One read of a batch: a device's key or a node's key (exactly one subject). */
17120
+ var QueryManyItemSchema = union([object({
17121
+ deviceId: number().int(),
17122
+ key: string(),
17123
+ scope: string().optional()
17124
+ }), object({
17125
+ forNodeId: string().min(1),
17126
+ key: string(),
17127
+ scope: string().optional()
17128
+ })]);
17129
+ var QueryManyEntrySchema = discriminatedUnion("ok", [object({
17130
+ ok: literal(true),
17131
+ result: QueryResultSchema
17132
+ }), object({
17133
+ ok: literal(false),
17134
+ error: string()
17135
+ })]);
17087
17136
  var TierStatusSchema = object({
17088
17137
  tier: DeviceHistoryResolutionSchema,
17089
17138
  /** `null` until the first background count answered. */
@@ -17139,16 +17188,22 @@ var DeviceHistoryStatusSchema = object({
17139
17188
  lastRefreshAt: number().nullable()
17140
17189
  })
17141
17190
  });
17142
- method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly()), method(object({ nodeId: string().min(1) }), array(SeriesInfoSchema).readonly(), { auth: "admin" }), method(object({
17191
+ method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly()), method(object({ forNodeId: string().min(1) }), array(SeriesInfoSchema).readonly(), { auth: "admin" }), method(object({
17143
17192
  deviceId: number().int(),
17144
17193
  ...QueryWindowShape
17145
17194
  }), QueryResultSchema), method(object({
17146
- nodeId: string().min(1),
17195
+ forNodeId: string().min(1),
17147
17196
  ...QueryWindowShape
17148
17197
  }), QueryResultSchema, { auth: "admin" }), method(object({
17198
+ items: array(QueryManyItemSchema).min(1).max(24),
17199
+ from: QueryWindowShape.from,
17200
+ to: QueryWindowShape.to,
17201
+ resolution: QueryWindowShape.resolution,
17202
+ maxPoints: QueryWindowShape.maxPoints
17203
+ }), object({ results: array(QueryManyEntrySchema).readonly() }), { auth: "admin" }), method(object({
17149
17204
  name: string().regex(/^[a-z0-9-]+$/),
17150
17205
  subjectKind: _enum(["device", "node"]),
17151
- kind: DeviceHistoryKindSchema,
17206
+ kind: DeviceHistoryProducerKindSchema,
17152
17207
  unit: string().optional(),
17153
17208
  displayName: string().min(1),
17154
17209
  ingest: _enum(["points", "buckets"])
@@ -40470,14 +40525,106 @@ var LogEntrySchema = object({
40470
40525
  meta: record(string(), unknown()).optional(),
40471
40526
  tags: record(string(), string()).optional()
40472
40527
  });
40473
- method(LogEntrySchema, _void(), { kind: "mutation" }), method(object({
40474
- scope: array(string()).optional(),
40528
+ /**
40529
+ * A history READ against one destination (D898).
40530
+ *
40531
+ * Every filter is applied by the PROVIDER, before the limit — a filter the
40532
+ * browser applied after the limit is what made a rare device's lines
40533
+ * unreachable behind a busy one's. `before` / `after` are cursors the provider
40534
+ * minted (opaque to everyone else): a file position for the rotated files, a
40535
+ * nanosecond timestamp for Loki.
40536
+ *
40537
+ * A read is BOUNDED by `budgetMs`: a filter that matches nothing on a 30-day
40538
+ * store answers `done: false` with the cursor it reached and the bytes it
40539
+ * scanned, and the caller decides whether to go on. That is what makes a long
40540
+ * scan show progress and stop when asked — `cancelRead` ends the slice in
40541
+ * flight, and not asking for the next slice ends the scan.
40542
+ */
40543
+ var LogReadQuerySchema = object({
40544
+ /** Correlates `cancelRead`. Caller-chosen, unique per in-flight read. */
40545
+ requestId: string().min(1).max(64).optional(),
40546
+ /** The device the line is about (`tags.deviceId`, numeric). */
40547
+ deviceId: number().int().optional(),
40548
+ /**
40549
+ * The emitting addon — bare manifest id; `@<version>` / `::<sub>` suffixes
40550
+ * match. Not `addonId`: a cap router reads that name as "which provider".
40551
+ */
40552
+ fromAddonId: string().min(1).max(200).optional(),
40553
+ /**
40554
+ * The emitting node: matches the agent that emitted the line, the node
40555
+ * itself, or a worker under it (`<agent>/<runner>`) — the `agentId`
40556
+ * semantics of `matchesLogTags`. Not `nodeId`: a cap router reads that
40557
+ * name as "which node's provider".
40558
+ */
40559
+ fromNodeId: string().min(1).max(200).optional(),
40560
+ /** Any other tag, exact match (AND). */
40561
+ tags: record(string(), union([string(), number()])).optional(),
40562
+ /** Severity FLOOR: this level and above. */
40475
40563
  level: LogLevelSchema.optional(),
40476
- since: date().optional(),
40477
- until: date().optional(),
40478
- limit: number().optional(),
40479
- tags: record(string(), string()).optional()
40480
- }), array(LogEntrySchema).readonly());
40564
+ /** Case-insensitive substring over message, scope, tag values and meta values. */
40565
+ text: string().min(1).max(200).optional(),
40566
+ /** Epoch ms, inclusive. */
40567
+ since: number().optional(),
40568
+ /** Epoch ms, inclusive. */
40569
+ until: number().optional(),
40570
+ /** Older than this cursor (exclusive). Absent with `after` absent ⇒ from the newest. */
40571
+ before: string().min(1).max(1024).optional(),
40572
+ /** Newer than this cursor (exclusive). */
40573
+ after: string().min(1).max(1024).optional(),
40574
+ limit: number().int().min(1).max(1e3).optional(),
40575
+ /** Wall-clock bound of this slice. The provider caps it. */
40576
+ budgetMs: number().int().min(50).max(1e4).optional()
40577
+ });
40578
+ var LogReadResultSchema = object({
40579
+ /** Newest first. */
40580
+ entries: array(object({
40581
+ /** `<bootId>.<seq>` minted by the emitting LogManager — the dedupe key. */
40582
+ id: string().optional(),
40583
+ /** Epoch ms. */
40584
+ timestamp: number(),
40585
+ level: LogLevelSchema,
40586
+ scope: string().optional(),
40587
+ message: string(),
40588
+ tags: record(string(), union([string(), number()])).optional(),
40589
+ meta: record(string(), unknown()).optional()
40590
+ })),
40591
+ /** Pass as `before` for the next older page; null when nothing older exists. */
40592
+ nextBefore: string().nullable(),
40593
+ /** Pass as `after` to read what arrived since; null when unknown. */
40594
+ nextAfter: string().nullable(),
40595
+ /** Bytes this slice read (files) or received (remote). Progress, not a promise. */
40596
+ scannedBytes: number().int().nonnegative(),
40597
+ /**
40598
+ * True when the scan in this direction reached the end of the store.
40599
+ * False with fewer than `limit` entries means the budget ran out first —
40600
+ * call again with `nextBefore` to go on.
40601
+ */
40602
+ done: boolean(),
40603
+ /** True when `cancelRead` ended this slice early. */
40604
+ cancelled: boolean().optional()
40605
+ });
40606
+ var LogReadCapabilitiesSchema = object({
40607
+ /** False ⇒ this destination only ships lines (console, forwarder, an unconfigured Loki). */
40608
+ readable: boolean(),
40609
+ /** Why not, when `readable` is false — rendered next to the source. */
40610
+ reason: string().nullable(),
40611
+ /** Filters the provider applies itself. A false one is applied by nobody. */
40612
+ filters: object({
40613
+ deviceId: boolean(),
40614
+ addonId: boolean(),
40615
+ nodeId: boolean(),
40616
+ tags: boolean(),
40617
+ level: boolean(),
40618
+ text: boolean(),
40619
+ timeRange: boolean()
40620
+ }),
40621
+ /** How far back the store reaches, when the provider knows (days). */
40622
+ retentionDays: number().nullable()
40623
+ });
40624
+ method(LogEntrySchema, _void(), { kind: "mutation" }), optionalMethod(_void(), LogReadCapabilitiesSchema, { auth: "admin" }), optionalMethod(LogReadQuerySchema, LogReadResultSchema, { auth: "admin" }), optionalMethod(object({ requestId: string().min(1).max(64) }), object({ cancelled: boolean() }), {
40625
+ kind: "mutation",
40626
+ auth: "admin"
40627
+ });
40481
40628
  /**
40482
40629
  * `login-method` — collection cap through which auth addons contribute
40483
40630
  * their pre-auth login surfaces to the login page. This is the SINGLE,
@@ -42195,9 +42342,11 @@ var alarmPanelCapability = {
42195
42342
  */
42196
42343
  durability: "restored",
42197
42344
  /**
42198
- * History (D850): none — enum state; arm/disarm history belongs in the events ledger.
42345
+ * History (D850): the panel's lifecycle state as an `enum` series —
42346
+ * change-only, no floor, so an `arming -> pending -> triggered` sequence of a
42347
+ * few seconds keeps every step. Who armed it stays in the events ledger.
42199
42348
  */
42200
- history: "none",
42349
+ history: { fields: { state: { kind: "enum" } } },
42201
42350
  /** Clock fields: written, but excluded from the compare that decides
42202
42351
  * whether persisting is worth a SQLite commit. */
42203
42352
  volatileStateFields: ["lastChangedAt"]
@@ -43075,6 +43224,33 @@ var NcRuleTargetSchema = object({
43075
43224
  params: record(string(), unknown()).optional()
43076
43225
  });
43077
43226
  /**
43227
+ * WHAT THE NOTIFICATION'S PICTURE IS (D897) — the ONE media choice of a rule.
43228
+ *
43229
+ * Every mode starts from the same CLEAN source frame of the trigger moment
43230
+ * (keyFrame → sceneFrame → lastSceneFrame, narrowed to the trigger instant and
43231
+ * to the zone that fired the rule) and renders it once at send time:
43232
+ * - `scene-boxes` — the whole scene, the subject outlined thick in the accent
43233
+ * colour and every OTHER track visible at that instant outlined thin, each
43234
+ * labelled with class and confidence ("dog 87%").
43235
+ * - `crop` — the subject cut out of that frame around its box at that instant.
43236
+ * - `clean` — the whole scene with nothing drawn on it.
43237
+ * - `none` — no picture.
43238
+ *
43239
+ * A mode that cannot be honoured (no box at that instant, a photograph with no
43240
+ * tracked subject) ships `clean` and names the reason in the log, per camera.
43241
+ * It replaces the `attach` × `frame` × `zoneCrop` triple, which let one rule
43242
+ * ship a crop on one event and a boxed scene on the next depending on which
43243
+ * stored kind had landed.
43244
+ */
43245
+ var NcMediaImageSchema = _enum([
43246
+ "scene-boxes",
43247
+ "crop",
43248
+ "clean",
43249
+ "none"
43250
+ ]);
43251
+ /**
43252
+ * @deprecated Read only by `normalizeNcMediaPolicy` (D897) — see {@link NcMediaImageSchema}.
43253
+ *
43078
43254
  * Media attachment policy (P1 still-image subset).
43079
43255
  * - `best` — the best AVAILABLE subject image at dispatch time (D-3).
43080
43256
  * - `best-matching` — the media that explains WHY the rule fired: a rule
@@ -43088,6 +43264,8 @@ var NcRuleTargetSchema = object({
43088
43264
  * - `none` — no attachment.
43089
43265
  */
43090
43266
  /**
43267
+ * @deprecated Read only by `normalizeNcMediaPolicy` (D897) — see {@link NcMediaImageSchema}.
43268
+ *
43091
43269
  * WHAT THE PICTURE SHOWS — chosen explicitly, because the implicit ladders
43092
43270
  * conflate it with the selection strategy and betray the request: asking for
43093
43271
  * the clean scene frame on an object-event owner used to start at
@@ -43116,16 +43294,29 @@ var NcMediaFrameSchema = _enum([
43116
43294
  */
43117
43295
  var NcLinkedCameraModeSchema = _enum(["mosaic", "each"]);
43118
43296
  var NcMediaPolicySchema = object({
43297
+ /**
43298
+ * The picture — see {@link NcMediaImageSchema}. Absent on a rule nobody has
43299
+ * saved since D897: `normalizeNcMediaPolicy` derives it from the legacy
43300
+ * triple below, at load and at every write, and the store keeps only this.
43301
+ */
43302
+ image: NcMediaImageSchema.optional(),
43303
+ /**
43304
+ * Draw the zone that FIRED the rule on the picture (`scene-boxes` / `clean`;
43305
+ * a `crop` never shows it). Valid only on a rule whose trigger is a zone —
43306
+ * `conditions.zones` or an occupancy zone — and refused on save otherwise.
43307
+ * Replaces `zoneCrop`.
43308
+ */
43309
+ showTriggerZone: boolean().optional(),
43310
+ /** @deprecated D897 — accepted from an editor that predates `image`, folded into it on save. */
43119
43311
  attach: _enum([
43120
43312
  "best",
43121
43313
  "best-matching",
43122
43314
  "keyFrame",
43123
43315
  "none"
43124
- ]).default("best"),
43125
- /** What the still shows. Absent = `cropped` (the historical `best` shape). */
43316
+ ]).optional(),
43317
+ /** @deprecated D897 — accepted from an editor that predates `image`, folded into it on save. */
43126
43318
  frame: NcMediaFrameSchema.optional(),
43127
- /** Crop the attached still to the rule's condition-zone bbox (padded) —
43128
- * "show me the ZONE", not the whole scene or the subject crop. */
43319
+ /** @deprecated D897 — folded into `image: 'clean'` + `showTriggerZone` on save. */
43129
43320
  zoneCrop: boolean().optional(),
43130
43321
  /**
43131
43322
  * Also attach a short GIF cut from the stream broker's clip ring around the
@@ -43297,7 +43488,9 @@ var NcRuleInputSchema = object({
43297
43488
  * targets.
43298
43489
  */
43299
43490
  targetUsers: array(string()).optional(),
43300
- media: NcMediaPolicySchema.default({ attach: "best" }),
43491
+ /** Absent = the kind's default picture (`resolveNcMediaImage`): the subject crop for a
43492
+ * detection, the clean scene for a sensor or a sound. Set explicitly on save (D897). */
43493
+ media: NcMediaPolicySchema.default({}),
43301
43494
  throttle: NcThrottleSchema.default({
43302
43495
  cooldownSec: 60,
43303
43496
  scope: "rule-device"
@@ -44234,13 +44427,37 @@ var NcAlarmModeOpeningsSchema = object({
44234
44427
  /** Covered devices whose state could not be read (D49): neither open nor closed. */
44235
44428
  unknown: array(number().int())
44236
44429
  });
44430
+ /**
44431
+ * One alarm INPUT — a (rule, device) pair — the operator bypassed until the
44432
+ * next disarm ("Bypass this input until disarm" on a trigger notification, or
44433
+ * `nc.bypassAlarmInput`). Reported so an armed alarm with a silenced input
44434
+ * never looks fully armed (D62: off must never look like broken).
44435
+ */
44436
+ var NcAlarmInputBypassViewSchema = object({
44437
+ ruleId: string(),
44438
+ /** The rule's current name (its frozen name when the rule is gone). */
44439
+ ruleName: string(),
44440
+ /** The input: the sensor of the match, else its camera. */
44441
+ deviceId: number().int(),
44442
+ /** The input's current name. */
44443
+ name: string(),
44444
+ /** When it was bypassed (ms epoch). */
44445
+ since: number(),
44446
+ /** Triggers from this input dropped since. */
44447
+ dropped: number().int().min(0)
44448
+ });
44237
44449
  var NcAlarmLiveSchema = object({
44238
44450
  state: AlarmStateSchema,
44239
44451
  /** The mode being armed into (exit delay) or held; null when disarmed. */
44240
44452
  targetMode: AlarmArmModeSchema.nullable(),
44241
44453
  availableModes: array(AlarmArmModeSchema),
44242
44454
  openings: array(NcAlarmModeOpeningsSchema),
44243
- exclusions: array(NcAlarmExclusionViewSchema)
44455
+ exclusions: array(NcAlarmExclusionViewSchema),
44456
+ /**
44457
+ * Inputs bypassed for the rest of this arm session; cleared on disarm.
44458
+ * Defaulted so an older hub answer still parses (as "none known").
44459
+ */
44460
+ bypassedInputs: array(NcAlarmInputBypassViewSchema).default([])
44244
44461
  });
44245
44462
  var NcAlarmConfigSchema = object({
44246
44463
  /**
@@ -54959,9 +55176,11 @@ var connectivityCapability = {
54959
55176
  */
54960
55177
  durability: "restored",
54961
55178
  /**
54962
- * History (D850): none — duplicates device-status.online (one authority for availability).
55179
+ * History (D850): `connected` as a boolean series — change-only, no floor. It
55180
+ * is the upstream entity's own link (a HA connectivity sensor), not the
55181
+ * device's reachability, which stays `device-status.online`.
54963
55182
  */
54964
- history: "none",
55183
+ history: { fields: { connected: { kind: "boolean" } } },
54965
55184
  /** Clock fields: written, but excluded from the compare that decides
54966
55185
  * whether persisting is worth a SQLite commit. */
54967
55186
  volatileStateFields: ["lastChangedAt"]
@@ -55785,11 +56004,22 @@ var dishwasherCapability = {
55785
56004
  },
55786
56005
  runtimeState: DishwasherStatusSchema,
55787
56006
  durability: "session",
55788
- history: { fields: { progressPercent: {
55789
- kind: "gauge",
55790
- unit: "%",
55791
- deadband: 2
55792
- } } }
56007
+ history: { fields: {
56008
+ progressPercent: {
56009
+ kind: "gauge",
56010
+ unit: "%",
56011
+ deadband: 2
56012
+ },
56013
+ state: { kind: "enum" },
56014
+ operationState: { kind: "enum" },
56015
+ remainingSeconds: {
56016
+ kind: "gauge",
56017
+ unit: "s",
56018
+ minIntervalMs: 6e4
56019
+ },
56020
+ doorOpen: { kind: "boolean" },
56021
+ powerOn: { kind: "boolean" }
56022
+ } }
55793
56023
  };
55794
56024
  var DoorbellStatusSchema = object({
55795
56025
  /** Ms epoch of the last press. null = never observed since this provider started. */
@@ -55906,9 +56136,15 @@ var enumSensorCapability = {
55906
56136
  */
55907
56137
  durability: "restored",
55908
56138
  /**
55909
- * History (D850): none — text/enum state has no history (non-goal).
56139
+ * History (D850): the value as an `enum` series (an appliance's program or
56140
+ * operation state, an HVAC action). The option set is per device, so the
56141
+ * value list is LEARNED as values are first seen (bounded). A sensor with a
56142
+ * `format` carries a timestamp, not a state, and is not recorded.
55910
56143
  */
55911
- history: "none",
56144
+ history: { fields: { value: {
56145
+ kind: "enum",
56146
+ skipWhenSet: "format"
56147
+ } } },
55912
56148
  /** Clock fields: written, but excluded from the compare that decides
55913
56149
  * whether persisting is worth a SQLite commit. */
55914
56150
  volatileStateFields: ["lastFetchedAt"]
@@ -57882,9 +58118,10 @@ var lockControlCapability = {
57882
58118
  */
57883
58119
  durability: "restored",
57884
58120
  /**
57885
- * History (D850): none — enum state; lock events belong in the events ledger.
58121
+ * History (D850): the lock's state as an `enum` series — change-only, no
58122
+ * floor: a jam or an unlock lasting seconds is the edge an operator looks for.
57886
58123
  */
57887
- history: "none",
58124
+ history: { fields: { state: { kind: "enum" } } },
57888
58125
  /** Clock fields: written, but excluded from the compare that decides
57889
58126
  * whether persisting is worth a SQLite commit. */
57890
58127
  volatileStateFields: ["lastChangedAt"]
@@ -58058,9 +58295,18 @@ var mediaPlayerCapability = {
58058
58295
  */
58059
58296
  durability: "session",
58060
58297
  /**
58061
- * History (D850): none — `positionMs` moves continuously while playing; volume is transient.
58298
+ * History (D850): volume (a level an operator or an automation sets; the
58299
+ * default 10 s floor folds a slider drag into its end value) and mute.
58300
+ * `positionMs` is not recorded: it moves continuously while playing.
58062
58301
  */
58063
- history: "none"
58302
+ history: { fields: {
58303
+ volumeLevel: {
58304
+ kind: "gauge",
58305
+ unit: "%",
58306
+ deadband: 1
58307
+ },
58308
+ isMuted: { kind: "boolean" }
58309
+ } }
58064
58310
  };
58065
58311
  /**
58066
58312
  * mesh-network — collection cap for mesh-VPN providers.
@@ -60204,9 +60450,24 @@ var NpuInfoSchema = object({
60204
60450
  name: string().optional(),
60205
60451
  generation: _enum(["xdna1", "xdna2"]).optional()
60206
60452
  });
60453
+ var CoralBusSchema = _enum(["usb", "pci"]);
60207
60454
  var CoralInfoSchema = object({
60208
60455
  type: literal("coral-edgetpu"),
60209
- bus: string().optional()
60456
+ /** Legacy single-bus report (older nodes) — read via `coralUsableUnits`. */
60457
+ bus: string().optional(),
60458
+ /** Legacy USB unit count (older nodes) — read via `coralUsableUnits`. */
60459
+ count: number().int().nonnegative().optional(),
60460
+ /** Usable units per bus — each one is its own `edgetpu:<bus>[:N]` device. */
60461
+ units: array(object({
60462
+ bus: CoralBusSchema,
60463
+ count: number().int().nonnegative()
60464
+ })).readonly().optional(),
60465
+ /** Present-but-unusable units, each with its typed reason (never "absent"). */
60466
+ unavailable: array(object({
60467
+ bus: CoralBusSchema,
60468
+ count: number().int().nonnegative(),
60469
+ reason: _enum(["driver-missing", "device-not-accessible"])
60470
+ })).readonly().optional()
60210
60471
  });
60211
60472
  var HardwareInfoSchema = object({
60212
60473
  platform: HardwarePlatformSchema,
@@ -63353,9 +63614,29 @@ var streamParamsCapability = {
63353
63614
  */
63354
63615
  durability: "restored",
63355
63616
  /**
63356
- * History (D850): none — encoder configuration.
63617
+ * History (D850): the configured bitrate and frame rate of the main and sub
63618
+ * profiles. Configuration, so change-only on the default floor: a point is an
63619
+ * operator's (or a tuner's) edit, which is exactly what a chart of a stream's
63620
+ * quality over time must show.
63357
63621
  */
63358
- history: "none",
63622
+ history: { fields: {
63623
+ "main.bitrate": {
63624
+ kind: "gauge",
63625
+ unit: "kbps"
63626
+ },
63627
+ "main.framerate": {
63628
+ kind: "gauge",
63629
+ unit: "fps"
63630
+ },
63631
+ "sub.bitrate": {
63632
+ kind: "gauge",
63633
+ unit: "kbps"
63634
+ },
63635
+ "sub.framerate": {
63636
+ kind: "gauge",
63637
+ unit: "fps"
63638
+ }
63639
+ } },
63359
63640
  /** Clock fields: written, but excluded from the compare that decides
63360
63641
  * whether persisting is worth a SQLite commit. */
63361
63642
  volatileStateFields: ["lastFetchedAt"]
@@ -66533,6 +66814,15 @@ var BaseDevice = class {
66533
66814
  * Drivers can use the `getProbeFlags()` helper to read the flag bag
66534
66815
  * with a typed cast.
66535
66816
  *
66817
+ * Answer what you KNOW. A plain array is read as the complete list only
66818
+ * while this device is `online` and probed; return
66819
+ * `accessoryChildrenUnknown(reason)` whenever you cannot know the list right
66820
+ * now (no credentials, parent not connected, a failed or partial read) —
66821
+ * the kernel then deletes nothing. Return `accessoryChildrenComplete(list)`
66822
+ * to say "connected, and this is the complete list" explicitly. A shrink is
66823
+ * deleted only after a second agreeing complete read on a later probe (D49;
66824
+ * `packages/system/src/kernel/moleculer/accessory-prune-gate.ts`).
66825
+ *
66536
66826
  * Default: no children.
66537
66827
  */
66538
66828
  getAccessoryChildren() {
@@ -70664,7 +70954,19 @@ Object.freeze({
70664
70954
  addonId: null,
70665
70955
  access: "view"
70666
70956
  },
70667
- "logDestination.query": {
70957
+ "logDestination.cancelRead": {
70958
+ capName: "log-destination",
70959
+ capScope: "system",
70960
+ addonId: null,
70961
+ access: "create"
70962
+ },
70963
+ "logDestination.describeRead": {
70964
+ capName: "log-destination",
70965
+ capScope: "system",
70966
+ addonId: null,
70967
+ access: "view"
70968
+ },
70969
+ "logDestination.read": {
70668
70970
  capName: "log-destination",
70669
70971
  capScope: "system",
70670
70972
  addonId: null,
@@ -76671,6 +76973,11 @@ Object.freeze({
76671
76973
  form: "single",
76672
76974
  optional: false
76673
76975
  }],
76976
+ "logDestination.read": [{
76977
+ name: "deviceId",
76978
+ form: "single",
76979
+ optional: true
76980
+ }],
76674
76981
  "mediaPlayer.getStatus": [{
76675
76982
  name: "deviceId",
76676
76983
  form: "single",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-velux",
3
- "version": "0.2.131",
3
+ "version": "0.2.133",
4
4
  "description": "Velux KLF-200 device-provider addon for CamStack — local-gateway window + shutter covers (positional, no tilt)",
5
5
  "keywords": [
6
6
  "camstack",