@camstack/addon-provider-unifi 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
  /**
@@ -54977,9 +55194,11 @@ var connectivityCapability = {
54977
55194
  */
54978
55195
  durability: "restored",
54979
55196
  /**
54980
- * History (D850): none — duplicates device-status.online (one authority for availability).
55197
+ * History (D850): `connected` as a boolean series — change-only, no floor. It
55198
+ * is the upstream entity's own link (a HA connectivity sensor), not the
55199
+ * device's reachability, which stays `device-status.online`.
54981
55200
  */
54982
- history: "none",
55201
+ history: { fields: { connected: { kind: "boolean" } } },
54983
55202
  /** Clock fields: written, but excluded from the compare that decides
54984
55203
  * whether persisting is worth a SQLite commit. */
54985
55204
  volatileStateFields: ["lastChangedAt"]
@@ -55803,11 +56022,22 @@ var dishwasherCapability = {
55803
56022
  },
55804
56023
  runtimeState: DishwasherStatusSchema,
55805
56024
  durability: "session",
55806
- history: { fields: { progressPercent: {
55807
- kind: "gauge",
55808
- unit: "%",
55809
- deadband: 2
55810
- } } }
56025
+ history: { fields: {
56026
+ progressPercent: {
56027
+ kind: "gauge",
56028
+ unit: "%",
56029
+ deadband: 2
56030
+ },
56031
+ state: { kind: "enum" },
56032
+ operationState: { kind: "enum" },
56033
+ remainingSeconds: {
56034
+ kind: "gauge",
56035
+ unit: "s",
56036
+ minIntervalMs: 6e4
56037
+ },
56038
+ doorOpen: { kind: "boolean" },
56039
+ powerOn: { kind: "boolean" }
56040
+ } }
55811
56041
  };
55812
56042
  var DoorbellStatusSchema = object({
55813
56043
  /** Ms epoch of the last press. null = never observed since this provider started. */
@@ -55924,9 +56154,15 @@ var enumSensorCapability = {
55924
56154
  */
55925
56155
  durability: "restored",
55926
56156
  /**
55927
- * History (D850): none — text/enum state has no history (non-goal).
56157
+ * History (D850): the value as an `enum` series (an appliance's program or
56158
+ * operation state, an HVAC action). The option set is per device, so the
56159
+ * value list is LEARNED as values are first seen (bounded). A sensor with a
56160
+ * `format` carries a timestamp, not a state, and is not recorded.
55928
56161
  */
55929
- history: "none",
56162
+ history: { fields: { value: {
56163
+ kind: "enum",
56164
+ skipWhenSet: "format"
56165
+ } } },
55930
56166
  /** Clock fields: written, but excluded from the compare that decides
55931
56167
  * whether persisting is worth a SQLite commit. */
55932
56168
  volatileStateFields: ["lastFetchedAt"]
@@ -57900,9 +58136,10 @@ var lockControlCapability = {
57900
58136
  */
57901
58137
  durability: "restored",
57902
58138
  /**
57903
- * History (D850): none — enum state; lock events belong in the events ledger.
58139
+ * History (D850): the lock's state as an `enum` series — change-only, no
58140
+ * floor: a jam or an unlock lasting seconds is the edge an operator looks for.
57904
58141
  */
57905
- history: "none",
58142
+ history: { fields: { state: { kind: "enum" } } },
57906
58143
  /** Clock fields: written, but excluded from the compare that decides
57907
58144
  * whether persisting is worth a SQLite commit. */
57908
58145
  volatileStateFields: ["lastChangedAt"]
@@ -58076,9 +58313,18 @@ var mediaPlayerCapability = {
58076
58313
  */
58077
58314
  durability: "session",
58078
58315
  /**
58079
- * History (D850): none — `positionMs` moves continuously while playing; volume is transient.
58316
+ * History (D850): volume (a level an operator or an automation sets; the
58317
+ * default 10 s floor folds a slider drag into its end value) and mute.
58318
+ * `positionMs` is not recorded: it moves continuously while playing.
58080
58319
  */
58081
- history: "none"
58320
+ history: { fields: {
58321
+ volumeLevel: {
58322
+ kind: "gauge",
58323
+ unit: "%",
58324
+ deadband: 1
58325
+ },
58326
+ isMuted: { kind: "boolean" }
58327
+ } }
58082
58328
  };
58083
58329
  /**
58084
58330
  * mesh-network — collection cap for mesh-VPN providers.
@@ -60222,9 +60468,24 @@ var NpuInfoSchema = object({
60222
60468
  name: string().optional(),
60223
60469
  generation: _enum(["xdna1", "xdna2"]).optional()
60224
60470
  });
60471
+ var CoralBusSchema = _enum(["usb", "pci"]);
60225
60472
  var CoralInfoSchema = object({
60226
60473
  type: literal("coral-edgetpu"),
60227
- bus: string().optional()
60474
+ /** Legacy single-bus report (older nodes) — read via `coralUsableUnits`. */
60475
+ bus: string().optional(),
60476
+ /** Legacy USB unit count (older nodes) — read via `coralUsableUnits`. */
60477
+ count: number().int().nonnegative().optional(),
60478
+ /** Usable units per bus — each one is its own `edgetpu:<bus>[:N]` device. */
60479
+ units: array(object({
60480
+ bus: CoralBusSchema,
60481
+ count: number().int().nonnegative()
60482
+ })).readonly().optional(),
60483
+ /** Present-but-unusable units, each with its typed reason (never "absent"). */
60484
+ unavailable: array(object({
60485
+ bus: CoralBusSchema,
60486
+ count: number().int().nonnegative(),
60487
+ reason: _enum(["driver-missing", "device-not-accessible"])
60488
+ })).readonly().optional()
60228
60489
  });
60229
60490
  var HardwareInfoSchema = object({
60230
60491
  platform: HardwarePlatformSchema,
@@ -63371,9 +63632,29 @@ var streamParamsCapability = {
63371
63632
  */
63372
63633
  durability: "restored",
63373
63634
  /**
63374
- * History (D850): none — encoder configuration.
63635
+ * History (D850): the configured bitrate and frame rate of the main and sub
63636
+ * profiles. Configuration, so change-only on the default floor: a point is an
63637
+ * operator's (or a tuner's) edit, which is exactly what a chart of a stream's
63638
+ * quality over time must show.
63375
63639
  */
63376
- history: "none",
63640
+ history: { fields: {
63641
+ "main.bitrate": {
63642
+ kind: "gauge",
63643
+ unit: "kbps"
63644
+ },
63645
+ "main.framerate": {
63646
+ kind: "gauge",
63647
+ unit: "fps"
63648
+ },
63649
+ "sub.bitrate": {
63650
+ kind: "gauge",
63651
+ unit: "kbps"
63652
+ },
63653
+ "sub.framerate": {
63654
+ kind: "gauge",
63655
+ unit: "fps"
63656
+ }
63657
+ } },
63377
63658
  /** Clock fields: written, but excluded from the compare that decides
63378
63659
  * whether persisting is worth a SQLite commit. */
63379
63660
  volatileStateFields: ["lastFetchedAt"]
@@ -66551,6 +66832,15 @@ var BaseDevice = class {
66551
66832
  * Drivers can use the `getProbeFlags()` helper to read the flag bag
66552
66833
  * with a typed cast.
66553
66834
  *
66835
+ * Answer what you KNOW. A plain array is read as the complete list only
66836
+ * while this device is `online` and probed; return
66837
+ * `accessoryChildrenUnknown(reason)` whenever you cannot know the list right
66838
+ * now (no credentials, parent not connected, a failed or partial read) —
66839
+ * the kernel then deletes nothing. Return `accessoryChildrenComplete(list)`
66840
+ * to say "connected, and this is the complete list" explicitly. A shrink is
66841
+ * deleted only after a second agreeing complete read on a later probe (D49;
66842
+ * `packages/system/src/kernel/moleculer/accessory-prune-gate.ts`).
66843
+ *
66554
66844
  * Default: no children.
66555
66845
  */
66556
66846
  getAccessoryChildren() {
@@ -70682,7 +70972,19 @@ Object.freeze({
70682
70972
  addonId: null,
70683
70973
  access: "view"
70684
70974
  },
70685
- "logDestination.query": {
70975
+ "logDestination.cancelRead": {
70976
+ capName: "log-destination",
70977
+ capScope: "system",
70978
+ addonId: null,
70979
+ access: "create"
70980
+ },
70981
+ "logDestination.describeRead": {
70982
+ capName: "log-destination",
70983
+ capScope: "system",
70984
+ addonId: null,
70985
+ access: "view"
70986
+ },
70987
+ "logDestination.read": {
70686
70988
  capName: "log-destination",
70687
70989
  capScope: "system",
70688
70990
  addonId: null,
@@ -76689,6 +76991,11 @@ Object.freeze({
76689
76991
  form: "single",
76690
76992
  optional: false
76691
76993
  }],
76994
+ "logDestination.read": [{
76995
+ name: "deviceId",
76996
+ form: "single",
76997
+ optional: true
76998
+ }],
76692
76999
  "mediaPlayer.getStatus": [{
76693
77000
  name: "deviceId",
76694
77001
  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
  /**
@@ -54976,9 +55193,11 @@ var connectivityCapability = {
54976
55193
  */
54977
55194
  durability: "restored",
54978
55195
  /**
54979
- * History (D850): none — duplicates device-status.online (one authority for availability).
55196
+ * History (D850): `connected` as a boolean series — change-only, no floor. It
55197
+ * is the upstream entity's own link (a HA connectivity sensor), not the
55198
+ * device's reachability, which stays `device-status.online`.
54980
55199
  */
54981
- history: "none",
55200
+ history: { fields: { connected: { kind: "boolean" } } },
54982
55201
  /** Clock fields: written, but excluded from the compare that decides
54983
55202
  * whether persisting is worth a SQLite commit. */
54984
55203
  volatileStateFields: ["lastChangedAt"]
@@ -55802,11 +56021,22 @@ var dishwasherCapability = {
55802
56021
  },
55803
56022
  runtimeState: DishwasherStatusSchema,
55804
56023
  durability: "session",
55805
- history: { fields: { progressPercent: {
55806
- kind: "gauge",
55807
- unit: "%",
55808
- deadband: 2
55809
- } } }
56024
+ history: { fields: {
56025
+ progressPercent: {
56026
+ kind: "gauge",
56027
+ unit: "%",
56028
+ deadband: 2
56029
+ },
56030
+ state: { kind: "enum" },
56031
+ operationState: { kind: "enum" },
56032
+ remainingSeconds: {
56033
+ kind: "gauge",
56034
+ unit: "s",
56035
+ minIntervalMs: 6e4
56036
+ },
56037
+ doorOpen: { kind: "boolean" },
56038
+ powerOn: { kind: "boolean" }
56039
+ } }
55810
56040
  };
55811
56041
  var DoorbellStatusSchema = object({
55812
56042
  /** Ms epoch of the last press. null = never observed since this provider started. */
@@ -55923,9 +56153,15 @@ var enumSensorCapability = {
55923
56153
  */
55924
56154
  durability: "restored",
55925
56155
  /**
55926
- * History (D850): none — text/enum state has no history (non-goal).
56156
+ * History (D850): the value as an `enum` series (an appliance's program or
56157
+ * operation state, an HVAC action). The option set is per device, so the
56158
+ * value list is LEARNED as values are first seen (bounded). A sensor with a
56159
+ * `format` carries a timestamp, not a state, and is not recorded.
55927
56160
  */
55928
- history: "none",
56161
+ history: { fields: { value: {
56162
+ kind: "enum",
56163
+ skipWhenSet: "format"
56164
+ } } },
55929
56165
  /** Clock fields: written, but excluded from the compare that decides
55930
56166
  * whether persisting is worth a SQLite commit. */
55931
56167
  volatileStateFields: ["lastFetchedAt"]
@@ -57899,9 +58135,10 @@ var lockControlCapability = {
57899
58135
  */
57900
58136
  durability: "restored",
57901
58137
  /**
57902
- * History (D850): none — enum state; lock events belong in the events ledger.
58138
+ * History (D850): the lock's state as an `enum` series — change-only, no
58139
+ * floor: a jam or an unlock lasting seconds is the edge an operator looks for.
57903
58140
  */
57904
- history: "none",
58141
+ history: { fields: { state: { kind: "enum" } } },
57905
58142
  /** Clock fields: written, but excluded from the compare that decides
57906
58143
  * whether persisting is worth a SQLite commit. */
57907
58144
  volatileStateFields: ["lastChangedAt"]
@@ -58075,9 +58312,18 @@ var mediaPlayerCapability = {
58075
58312
  */
58076
58313
  durability: "session",
58077
58314
  /**
58078
- * History (D850): none — `positionMs` moves continuously while playing; volume is transient.
58315
+ * History (D850): volume (a level an operator or an automation sets; the
58316
+ * default 10 s floor folds a slider drag into its end value) and mute.
58317
+ * `positionMs` is not recorded: it moves continuously while playing.
58079
58318
  */
58080
- history: "none"
58319
+ history: { fields: {
58320
+ volumeLevel: {
58321
+ kind: "gauge",
58322
+ unit: "%",
58323
+ deadband: 1
58324
+ },
58325
+ isMuted: { kind: "boolean" }
58326
+ } }
58081
58327
  };
58082
58328
  /**
58083
58329
  * mesh-network — collection cap for mesh-VPN providers.
@@ -60221,9 +60467,24 @@ var NpuInfoSchema = object({
60221
60467
  name: string().optional(),
60222
60468
  generation: _enum(["xdna1", "xdna2"]).optional()
60223
60469
  });
60470
+ var CoralBusSchema = _enum(["usb", "pci"]);
60224
60471
  var CoralInfoSchema = object({
60225
60472
  type: literal("coral-edgetpu"),
60226
- bus: string().optional()
60473
+ /** Legacy single-bus report (older nodes) — read via `coralUsableUnits`. */
60474
+ bus: string().optional(),
60475
+ /** Legacy USB unit count (older nodes) — read via `coralUsableUnits`. */
60476
+ count: number().int().nonnegative().optional(),
60477
+ /** Usable units per bus — each one is its own `edgetpu:<bus>[:N]` device. */
60478
+ units: array(object({
60479
+ bus: CoralBusSchema,
60480
+ count: number().int().nonnegative()
60481
+ })).readonly().optional(),
60482
+ /** Present-but-unusable units, each with its typed reason (never "absent"). */
60483
+ unavailable: array(object({
60484
+ bus: CoralBusSchema,
60485
+ count: number().int().nonnegative(),
60486
+ reason: _enum(["driver-missing", "device-not-accessible"])
60487
+ })).readonly().optional()
60227
60488
  });
60228
60489
  var HardwareInfoSchema = object({
60229
60490
  platform: HardwarePlatformSchema,
@@ -63370,9 +63631,29 @@ var streamParamsCapability = {
63370
63631
  */
63371
63632
  durability: "restored",
63372
63633
  /**
63373
- * History (D850): none — encoder configuration.
63634
+ * History (D850): the configured bitrate and frame rate of the main and sub
63635
+ * profiles. Configuration, so change-only on the default floor: a point is an
63636
+ * operator's (or a tuner's) edit, which is exactly what a chart of a stream's
63637
+ * quality over time must show.
63374
63638
  */
63375
- history: "none",
63639
+ history: { fields: {
63640
+ "main.bitrate": {
63641
+ kind: "gauge",
63642
+ unit: "kbps"
63643
+ },
63644
+ "main.framerate": {
63645
+ kind: "gauge",
63646
+ unit: "fps"
63647
+ },
63648
+ "sub.bitrate": {
63649
+ kind: "gauge",
63650
+ unit: "kbps"
63651
+ },
63652
+ "sub.framerate": {
63653
+ kind: "gauge",
63654
+ unit: "fps"
63655
+ }
63656
+ } },
63376
63657
  /** Clock fields: written, but excluded from the compare that decides
63377
63658
  * whether persisting is worth a SQLite commit. */
63378
63659
  volatileStateFields: ["lastFetchedAt"]
@@ -66550,6 +66831,15 @@ var BaseDevice = class {
66550
66831
  * Drivers can use the `getProbeFlags()` helper to read the flag bag
66551
66832
  * with a typed cast.
66552
66833
  *
66834
+ * Answer what you KNOW. A plain array is read as the complete list only
66835
+ * while this device is `online` and probed; return
66836
+ * `accessoryChildrenUnknown(reason)` whenever you cannot know the list right
66837
+ * now (no credentials, parent not connected, a failed or partial read) —
66838
+ * the kernel then deletes nothing. Return `accessoryChildrenComplete(list)`
66839
+ * to say "connected, and this is the complete list" explicitly. A shrink is
66840
+ * deleted only after a second agreeing complete read on a later probe (D49;
66841
+ * `packages/system/src/kernel/moleculer/accessory-prune-gate.ts`).
66842
+ *
66553
66843
  * Default: no children.
66554
66844
  */
66555
66845
  getAccessoryChildren() {
@@ -70681,7 +70971,19 @@ Object.freeze({
70681
70971
  addonId: null,
70682
70972
  access: "view"
70683
70973
  },
70684
- "logDestination.query": {
70974
+ "logDestination.cancelRead": {
70975
+ capName: "log-destination",
70976
+ capScope: "system",
70977
+ addonId: null,
70978
+ access: "create"
70979
+ },
70980
+ "logDestination.describeRead": {
70981
+ capName: "log-destination",
70982
+ capScope: "system",
70983
+ addonId: null,
70984
+ access: "view"
70985
+ },
70986
+ "logDestination.read": {
70685
70987
  capName: "log-destination",
70686
70988
  capScope: "system",
70687
70989
  addonId: null,
@@ -76688,6 +76990,11 @@ Object.freeze({
76688
76990
  form: "single",
76689
76991
  optional: false
76690
76992
  }],
76993
+ "logDestination.read": [{
76994
+ name: "deviceId",
76995
+ form: "single",
76996
+ optional: true
76997
+ }],
76691
76998
  "mediaPlayer.getStatus": [{
76692
76999
  name: "deviceId",
76693
77000
  form: "single",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-unifi",
3
- "version": "0.2.131",
3
+ "version": "0.2.133",
4
4
  "description": "UniFi Network controller device-provider addon for CamStack — local-controller infra switches/APs (as containers) + network-client presence. NO cameras/Protect.",
5
5
  "keywords": [
6
6
  "camstack",