@camstack/addon-provider-tuya 0.2.130 → 0.2.132

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
@@ -6234,7 +6234,7 @@ var ZodIssueCode = {
6234
6234
  var ZodFirstPartyTypeKind;
6235
6235
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
6236
6236
  //#endregion
6237
- //#region ../types/dist/sleep-yKL5gfrH.mjs
6237
+ //#region ../types/dist/sleep-BSuCCFjf.mjs
6238
6238
  /**
6239
6239
  * The audio chunk plane's byte format, and the ONE expansion from a coded
6240
6240
  * window to float samples (D455).
@@ -17814,7 +17814,19 @@ var DeviceHistorySubjectSchema = discriminatedUnion("kind", [object({
17814
17814
  kind: literal("node"),
17815
17815
  nodeId: string().min(1)
17816
17816
  })]);
17817
+ /**
17818
+ * `enum` stores a STATE as the ordinal of its value in the series' value list
17819
+ * (`DeviceHistorySeriesInfo.values`, append-only, so an ordinal never changes
17820
+ * meaning); a rollup keeps the time spent in each state (`states`).
17821
+ */
17817
17822
  var DeviceHistoryKindSchema = _enum([
17823
+ "gauge",
17824
+ "counter",
17825
+ "boolean",
17826
+ "enum"
17827
+ ]);
17828
+ /** What a PRODUCER may declare. `enum` is cap-only: its value list is the cap field's. */
17829
+ var DeviceHistoryProducerKindSchema = _enum([
17818
17830
  "gauge",
17819
17831
  "counter",
17820
17832
  "boolean"
@@ -17851,7 +17863,13 @@ var SeriesInfoSchema = object({
17851
17863
  /** `null` is unknown (a `unitFrom` series whose device does not state a unit right now), never a guess. */
17852
17864
  unit: string().nullable(),
17853
17865
  displayName: string(),
17854
- source: _enum(["cap", "addon"]),
17866
+ source: _enum([
17867
+ "cap",
17868
+ "addon",
17869
+ "derived"
17870
+ ]),
17871
+ /** `enum`: the value of each ordinal (index = ordinal); `null` for every other kind. */
17872
+ values: array(string()).readonly().nullable(),
17855
17873
  firstTs: number(),
17856
17874
  lastTs: number()
17857
17875
  });
@@ -17865,17 +17883,31 @@ var QueryPointSchema = object({
17865
17883
  twMean: number().nullable(),
17866
17884
  min: number(),
17867
17885
  max: number(),
17868
- /** `null` is unknown, never zero (D393). */
17869
- last: number().nullable()
17886
+ /** `null` is unknown, never zero (D393). For an `enum` series: the ordinal of {@link state}. */
17887
+ last: number().nullable(),
17888
+ /**
17889
+ * The increase over the point: a `counter`'s growth since the previous point
17890
+ * or bucket (a drop is a reset, counted from zero), and for
17891
+ * {@link DEVICE_HISTORY_ENERGY_KEY} the kWh used in the bucket. `null` for
17892
+ * every other kind, and when it cannot be known.
17893
+ */
17894
+ delta: number().nullable(),
17895
+ /** `enum`: the state in force at the end of the point (the name of `last`); `null` otherwise. */
17896
+ state: string().nullable(),
17897
+ /** `enum` rollup: milliseconds spent in each state inside the bucket; `null` for raw points and other kinds. */
17898
+ states: record(string(), number()).nullable()
17870
17899
  });
17871
17900
  var QuerySeriesSchema = object({
17872
17901
  scope: string(),
17873
17902
  /** The last point STRICTLY BEFORE `from` in the chosen tier, so a step chart can start at the held value. */
17874
17903
  before: object({
17875
17904
  t: number(),
17876
- value: number().nullable()
17905
+ value: number().nullable(),
17906
+ state: string().nullable()
17877
17907
  }).nullable(),
17878
- points: array(QueryPointSchema).readonly()
17908
+ points: array(QueryPointSchema).readonly(),
17909
+ /** A derived key: the stored key its points were computed from; `null` for a stored series. */
17910
+ derivedFrom: string().nullable()
17879
17911
  });
17880
17912
  /** The window part of a query, shared by the device and node forms. */
17881
17913
  var QueryWindowShape = {
@@ -17891,6 +17923,23 @@ var QueryResultSchema = object({
17891
17923
  series: array(QuerySeriesSchema).readonly(),
17892
17924
  truncated: boolean()
17893
17925
  });
17926
+ /** One read of a batch: a device's key or a node's key (exactly one subject). */
17927
+ var QueryManyItemSchema = union([object({
17928
+ deviceId: number().int(),
17929
+ key: string(),
17930
+ scope: string().optional()
17931
+ }), object({
17932
+ forNodeId: string().min(1),
17933
+ key: string(),
17934
+ scope: string().optional()
17935
+ })]);
17936
+ var QueryManyEntrySchema = discriminatedUnion("ok", [object({
17937
+ ok: literal(true),
17938
+ result: QueryResultSchema
17939
+ }), object({
17940
+ ok: literal(false),
17941
+ error: string()
17942
+ })]);
17894
17943
  var TierStatusSchema = object({
17895
17944
  tier: DeviceHistoryResolutionSchema,
17896
17945
  /** `null` until the first background count answered. */
@@ -17946,16 +17995,22 @@ var DeviceHistoryStatusSchema = object({
17946
17995
  lastRefreshAt: number().nullable()
17947
17996
  })
17948
17997
  });
17949
- method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly()), method(object({ nodeId: string().min(1) }), array(SeriesInfoSchema).readonly(), { auth: "admin" }), method(object({
17998
+ method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly()), method(object({ forNodeId: string().min(1) }), array(SeriesInfoSchema).readonly(), { auth: "admin" }), method(object({
17950
17999
  deviceId: number().int(),
17951
18000
  ...QueryWindowShape
17952
18001
  }), QueryResultSchema), method(object({
17953
- nodeId: string().min(1),
18002
+ forNodeId: string().min(1),
17954
18003
  ...QueryWindowShape
17955
18004
  }), QueryResultSchema, { auth: "admin" }), method(object({
18005
+ items: array(QueryManyItemSchema).min(1).max(24),
18006
+ from: QueryWindowShape.from,
18007
+ to: QueryWindowShape.to,
18008
+ resolution: QueryWindowShape.resolution,
18009
+ maxPoints: QueryWindowShape.maxPoints
18010
+ }), object({ results: array(QueryManyEntrySchema).readonly() }), { auth: "admin" }), method(object({
17956
18011
  name: string().regex(/^[a-z0-9-]+$/),
17957
18012
  subjectKind: _enum(["device", "node"]),
17958
- kind: DeviceHistoryKindSchema,
18013
+ kind: DeviceHistoryProducerKindSchema,
17959
18014
  unit: string().optional(),
17960
18015
  displayName: string().min(1),
17961
18016
  ingest: _enum(["points", "buckets"])
@@ -41181,14 +41236,106 @@ var LogEntrySchema = object({
41181
41236
  meta: record(string(), unknown()).optional(),
41182
41237
  tags: record(string(), string()).optional()
41183
41238
  });
41184
- method(LogEntrySchema, _void(), { kind: "mutation" }), method(object({
41185
- scope: array(string()).optional(),
41239
+ /**
41240
+ * A history READ against one destination (D898).
41241
+ *
41242
+ * Every filter is applied by the PROVIDER, before the limit — a filter the
41243
+ * browser applied after the limit is what made a rare device's lines
41244
+ * unreachable behind a busy one's. `before` / `after` are cursors the provider
41245
+ * minted (opaque to everyone else): a file position for the rotated files, a
41246
+ * nanosecond timestamp for Loki.
41247
+ *
41248
+ * A read is BOUNDED by `budgetMs`: a filter that matches nothing on a 30-day
41249
+ * store answers `done: false` with the cursor it reached and the bytes it
41250
+ * scanned, and the caller decides whether to go on. That is what makes a long
41251
+ * scan show progress and stop when asked — `cancelRead` ends the slice in
41252
+ * flight, and not asking for the next slice ends the scan.
41253
+ */
41254
+ var LogReadQuerySchema = object({
41255
+ /** Correlates `cancelRead`. Caller-chosen, unique per in-flight read. */
41256
+ requestId: string().min(1).max(64).optional(),
41257
+ /** The device the line is about (`tags.deviceId`, numeric). */
41258
+ deviceId: number().int().optional(),
41259
+ /**
41260
+ * The emitting addon — bare manifest id; `@<version>` / `::<sub>` suffixes
41261
+ * match. Not `addonId`: a cap router reads that name as "which provider".
41262
+ */
41263
+ fromAddonId: string().min(1).max(200).optional(),
41264
+ /**
41265
+ * The emitting node: matches the agent that emitted the line, the node
41266
+ * itself, or a worker under it (`<agent>/<runner>`) — the `agentId`
41267
+ * semantics of `matchesLogTags`. Not `nodeId`: a cap router reads that
41268
+ * name as "which node's provider".
41269
+ */
41270
+ fromNodeId: string().min(1).max(200).optional(),
41271
+ /** Any other tag, exact match (AND). */
41272
+ tags: record(string(), union([string(), number()])).optional(),
41273
+ /** Severity FLOOR: this level and above. */
41186
41274
  level: LogLevelSchema.optional(),
41187
- since: date().optional(),
41188
- until: date().optional(),
41189
- limit: number().optional(),
41190
- tags: record(string(), string()).optional()
41191
- }), array(LogEntrySchema).readonly());
41275
+ /** Case-insensitive substring over message, scope, tag values and meta values. */
41276
+ text: string().min(1).max(200).optional(),
41277
+ /** Epoch ms, inclusive. */
41278
+ since: number().optional(),
41279
+ /** Epoch ms, inclusive. */
41280
+ until: number().optional(),
41281
+ /** Older than this cursor (exclusive). Absent with `after` absent ⇒ from the newest. */
41282
+ before: string().min(1).max(1024).optional(),
41283
+ /** Newer than this cursor (exclusive). */
41284
+ after: string().min(1).max(1024).optional(),
41285
+ limit: number().int().min(1).max(1e3).optional(),
41286
+ /** Wall-clock bound of this slice. The provider caps it. */
41287
+ budgetMs: number().int().min(50).max(1e4).optional()
41288
+ });
41289
+ var LogReadResultSchema = object({
41290
+ /** Newest first. */
41291
+ entries: array(object({
41292
+ /** `<bootId>.<seq>` minted by the emitting LogManager — the dedupe key. */
41293
+ id: string().optional(),
41294
+ /** Epoch ms. */
41295
+ timestamp: number(),
41296
+ level: LogLevelSchema,
41297
+ scope: string().optional(),
41298
+ message: string(),
41299
+ tags: record(string(), union([string(), number()])).optional(),
41300
+ meta: record(string(), unknown()).optional()
41301
+ })),
41302
+ /** Pass as `before` for the next older page; null when nothing older exists. */
41303
+ nextBefore: string().nullable(),
41304
+ /** Pass as `after` to read what arrived since; null when unknown. */
41305
+ nextAfter: string().nullable(),
41306
+ /** Bytes this slice read (files) or received (remote). Progress, not a promise. */
41307
+ scannedBytes: number().int().nonnegative(),
41308
+ /**
41309
+ * True when the scan in this direction reached the end of the store.
41310
+ * False with fewer than `limit` entries means the budget ran out first —
41311
+ * call again with `nextBefore` to go on.
41312
+ */
41313
+ done: boolean(),
41314
+ /** True when `cancelRead` ended this slice early. */
41315
+ cancelled: boolean().optional()
41316
+ });
41317
+ var LogReadCapabilitiesSchema = object({
41318
+ /** False ⇒ this destination only ships lines (console, forwarder, an unconfigured Loki). */
41319
+ readable: boolean(),
41320
+ /** Why not, when `readable` is false — rendered next to the source. */
41321
+ reason: string().nullable(),
41322
+ /** Filters the provider applies itself. A false one is applied by nobody. */
41323
+ filters: object({
41324
+ deviceId: boolean(),
41325
+ addonId: boolean(),
41326
+ nodeId: boolean(),
41327
+ tags: boolean(),
41328
+ level: boolean(),
41329
+ text: boolean(),
41330
+ timeRange: boolean()
41331
+ }),
41332
+ /** How far back the store reaches, when the provider knows (days). */
41333
+ retentionDays: number().nullable()
41334
+ });
41335
+ 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() }), {
41336
+ kind: "mutation",
41337
+ auth: "admin"
41338
+ });
41192
41339
  /**
41193
41340
  * `login-method` — collection cap through which auth addons contribute
41194
41341
  * their pre-auth login surfaces to the login page. This is the SINGLE,
@@ -42906,9 +43053,11 @@ var alarmPanelCapability = {
42906
43053
  */
42907
43054
  durability: "restored",
42908
43055
  /**
42909
- * History (D850): none — enum state; arm/disarm history belongs in the events ledger.
43056
+ * History (D850): the panel's lifecycle state as an `enum` series —
43057
+ * change-only, no floor, so an `arming -> pending -> triggered` sequence of a
43058
+ * few seconds keeps every step. Who armed it stays in the events ledger.
42910
43059
  */
42911
- history: "none",
43060
+ history: { fields: { state: { kind: "enum" } } },
42912
43061
  /** Clock fields: written, but excluded from the compare that decides
42913
43062
  * whether persisting is worth a SQLite commit. */
42914
43063
  volatileStateFields: ["lastChangedAt"]
@@ -43786,6 +43935,33 @@ var NcRuleTargetSchema = object({
43786
43935
  params: record(string(), unknown()).optional()
43787
43936
  });
43788
43937
  /**
43938
+ * WHAT THE NOTIFICATION'S PICTURE IS (D897) — the ONE media choice of a rule.
43939
+ *
43940
+ * Every mode starts from the same CLEAN source frame of the trigger moment
43941
+ * (keyFrame → sceneFrame → lastSceneFrame, narrowed to the trigger instant and
43942
+ * to the zone that fired the rule) and renders it once at send time:
43943
+ * - `scene-boxes` — the whole scene, the subject outlined thick in the accent
43944
+ * colour and every OTHER track visible at that instant outlined thin, each
43945
+ * labelled with class and confidence ("dog 87%").
43946
+ * - `crop` — the subject cut out of that frame around its box at that instant.
43947
+ * - `clean` — the whole scene with nothing drawn on it.
43948
+ * - `none` — no picture.
43949
+ *
43950
+ * A mode that cannot be honoured (no box at that instant, a photograph with no
43951
+ * tracked subject) ships `clean` and names the reason in the log, per camera.
43952
+ * It replaces the `attach` × `frame` × `zoneCrop` triple, which let one rule
43953
+ * ship a crop on one event and a boxed scene on the next depending on which
43954
+ * stored kind had landed.
43955
+ */
43956
+ var NcMediaImageSchema = _enum([
43957
+ "scene-boxes",
43958
+ "crop",
43959
+ "clean",
43960
+ "none"
43961
+ ]);
43962
+ /**
43963
+ * @deprecated Read only by `normalizeNcMediaPolicy` (D897) — see {@link NcMediaImageSchema}.
43964
+ *
43789
43965
  * Media attachment policy (P1 still-image subset).
43790
43966
  * - `best` — the best AVAILABLE subject image at dispatch time (D-3).
43791
43967
  * - `best-matching` — the media that explains WHY the rule fired: a rule
@@ -43799,6 +43975,8 @@ var NcRuleTargetSchema = object({
43799
43975
  * - `none` — no attachment.
43800
43976
  */
43801
43977
  /**
43978
+ * @deprecated Read only by `normalizeNcMediaPolicy` (D897) — see {@link NcMediaImageSchema}.
43979
+ *
43802
43980
  * WHAT THE PICTURE SHOWS — chosen explicitly, because the implicit ladders
43803
43981
  * conflate it with the selection strategy and betray the request: asking for
43804
43982
  * the clean scene frame on an object-event owner used to start at
@@ -43827,16 +44005,29 @@ var NcMediaFrameSchema = _enum([
43827
44005
  */
43828
44006
  var NcLinkedCameraModeSchema = _enum(["mosaic", "each"]);
43829
44007
  var NcMediaPolicySchema = object({
44008
+ /**
44009
+ * The picture — see {@link NcMediaImageSchema}. Absent on a rule nobody has
44010
+ * saved since D897: `normalizeNcMediaPolicy` derives it from the legacy
44011
+ * triple below, at load and at every write, and the store keeps only this.
44012
+ */
44013
+ image: NcMediaImageSchema.optional(),
44014
+ /**
44015
+ * Draw the zone that FIRED the rule on the picture (`scene-boxes` / `clean`;
44016
+ * a `crop` never shows it). Valid only on a rule whose trigger is a zone —
44017
+ * `conditions.zones` or an occupancy zone — and refused on save otherwise.
44018
+ * Replaces `zoneCrop`.
44019
+ */
44020
+ showTriggerZone: boolean().optional(),
44021
+ /** @deprecated D897 — accepted from an editor that predates `image`, folded into it on save. */
43830
44022
  attach: _enum([
43831
44023
  "best",
43832
44024
  "best-matching",
43833
44025
  "keyFrame",
43834
44026
  "none"
43835
- ]).default("best"),
43836
- /** What the still shows. Absent = `cropped` (the historical `best` shape). */
44027
+ ]).optional(),
44028
+ /** @deprecated D897 — accepted from an editor that predates `image`, folded into it on save. */
43837
44029
  frame: NcMediaFrameSchema.optional(),
43838
- /** Crop the attached still to the rule's condition-zone bbox (padded) —
43839
- * "show me the ZONE", not the whole scene or the subject crop. */
44030
+ /** @deprecated D897 — folded into `image: 'clean'` + `showTriggerZone` on save. */
43840
44031
  zoneCrop: boolean().optional(),
43841
44032
  /**
43842
44033
  * Also attach a short GIF cut from the stream broker's clip ring around the
@@ -44008,7 +44199,9 @@ var NcRuleInputSchema = object({
44008
44199
  * targets.
44009
44200
  */
44010
44201
  targetUsers: array(string()).optional(),
44011
- media: NcMediaPolicySchema.default({ attach: "best" }),
44202
+ /** Absent = the kind's default picture (`resolveNcMediaImage`): the subject crop for a
44203
+ * detection, the clean scene for a sensor or a sound. Set explicitly on save (D897). */
44204
+ media: NcMediaPolicySchema.default({}),
44012
44205
  throttle: NcThrottleSchema.default({
44013
44206
  cooldownSec: 60,
44014
44207
  scope: "rule-device"
@@ -44945,13 +45138,37 @@ var NcAlarmModeOpeningsSchema = object({
44945
45138
  /** Covered devices whose state could not be read (D49): neither open nor closed. */
44946
45139
  unknown: array(number().int())
44947
45140
  });
45141
+ /**
45142
+ * One alarm INPUT — a (rule, device) pair — the operator bypassed until the
45143
+ * next disarm ("Bypass this input until disarm" on a trigger notification, or
45144
+ * `nc.bypassAlarmInput`). Reported so an armed alarm with a silenced input
45145
+ * never looks fully armed (D62: off must never look like broken).
45146
+ */
45147
+ var NcAlarmInputBypassViewSchema = object({
45148
+ ruleId: string(),
45149
+ /** The rule's current name (its frozen name when the rule is gone). */
45150
+ ruleName: string(),
45151
+ /** The input: the sensor of the match, else its camera. */
45152
+ deviceId: number().int(),
45153
+ /** The input's current name. */
45154
+ name: string(),
45155
+ /** When it was bypassed (ms epoch). */
45156
+ since: number(),
45157
+ /** Triggers from this input dropped since. */
45158
+ dropped: number().int().min(0)
45159
+ });
44948
45160
  var NcAlarmLiveSchema = object({
44949
45161
  state: AlarmStateSchema,
44950
45162
  /** The mode being armed into (exit delay) or held; null when disarmed. */
44951
45163
  targetMode: AlarmArmModeSchema.nullable(),
44952
45164
  availableModes: array(AlarmArmModeSchema),
44953
45165
  openings: array(NcAlarmModeOpeningsSchema),
44954
- exclusions: array(NcAlarmExclusionViewSchema)
45166
+ exclusions: array(NcAlarmExclusionViewSchema),
45167
+ /**
45168
+ * Inputs bypassed for the rest of this arm session; cleared on disarm.
45169
+ * Defaulted so an older hub answer still parses (as "none known").
45170
+ */
45171
+ bypassedInputs: array(NcAlarmInputBypassViewSchema).default([])
44955
45172
  });
44956
45173
  var NcAlarmConfigSchema = object({
44957
45174
  /**
@@ -55678,9 +55895,11 @@ var connectivityCapability = {
55678
55895
  */
55679
55896
  durability: "restored",
55680
55897
  /**
55681
- * History (D850): none — duplicates device-status.online (one authority for availability).
55898
+ * History (D850): `connected` as a boolean series — change-only, no floor. It
55899
+ * is the upstream entity's own link (a HA connectivity sensor), not the
55900
+ * device's reachability, which stays `device-status.online`.
55682
55901
  */
55683
- history: "none",
55902
+ history: { fields: { connected: { kind: "boolean" } } },
55684
55903
  /** Clock fields: written, but excluded from the compare that decides
55685
55904
  * whether persisting is worth a SQLite commit. */
55686
55905
  volatileStateFields: ["lastChangedAt"]
@@ -56504,11 +56723,22 @@ var dishwasherCapability = {
56504
56723
  },
56505
56724
  runtimeState: DishwasherStatusSchema,
56506
56725
  durability: "session",
56507
- history: { fields: { progressPercent: {
56508
- kind: "gauge",
56509
- unit: "%",
56510
- deadband: 2
56511
- } } }
56726
+ history: { fields: {
56727
+ progressPercent: {
56728
+ kind: "gauge",
56729
+ unit: "%",
56730
+ deadband: 2
56731
+ },
56732
+ state: { kind: "enum" },
56733
+ operationState: { kind: "enum" },
56734
+ remainingSeconds: {
56735
+ kind: "gauge",
56736
+ unit: "s",
56737
+ minIntervalMs: 6e4
56738
+ },
56739
+ doorOpen: { kind: "boolean" },
56740
+ powerOn: { kind: "boolean" }
56741
+ } }
56512
56742
  };
56513
56743
  var DoorbellStatusSchema = object({
56514
56744
  /** Ms epoch of the last press. null = never observed since this provider started. */
@@ -56625,9 +56855,15 @@ var enumSensorCapability = {
56625
56855
  */
56626
56856
  durability: "restored",
56627
56857
  /**
56628
- * History (D850): none — text/enum state has no history (non-goal).
56858
+ * History (D850): the value as an `enum` series (an appliance's program or
56859
+ * operation state, an HVAC action). The option set is per device, so the
56860
+ * value list is LEARNED as values are first seen (bounded). A sensor with a
56861
+ * `format` carries a timestamp, not a state, and is not recorded.
56629
56862
  */
56630
- history: "none",
56863
+ history: { fields: { value: {
56864
+ kind: "enum",
56865
+ skipWhenSet: "format"
56866
+ } } },
56631
56867
  /** Clock fields: written, but excluded from the compare that decides
56632
56868
  * whether persisting is worth a SQLite commit. */
56633
56869
  volatileStateFields: ["lastFetchedAt"]
@@ -58601,9 +58837,10 @@ var lockControlCapability = {
58601
58837
  */
58602
58838
  durability: "restored",
58603
58839
  /**
58604
- * History (D850): none — enum state; lock events belong in the events ledger.
58840
+ * History (D850): the lock's state as an `enum` series — change-only, no
58841
+ * floor: a jam or an unlock lasting seconds is the edge an operator looks for.
58605
58842
  */
58606
- history: "none",
58843
+ history: { fields: { state: { kind: "enum" } } },
58607
58844
  /** Clock fields: written, but excluded from the compare that decides
58608
58845
  * whether persisting is worth a SQLite commit. */
58609
58846
  volatileStateFields: ["lastChangedAt"]
@@ -58777,9 +59014,18 @@ var mediaPlayerCapability = {
58777
59014
  */
58778
59015
  durability: "session",
58779
59016
  /**
58780
- * History (D850): none — `positionMs` moves continuously while playing; volume is transient.
59017
+ * History (D850): volume (a level an operator or an automation sets; the
59018
+ * default 10 s floor folds a slider drag into its end value) and mute.
59019
+ * `positionMs` is not recorded: it moves continuously while playing.
58781
59020
  */
58782
- history: "none"
59021
+ history: { fields: {
59022
+ volumeLevel: {
59023
+ kind: "gauge",
59024
+ unit: "%",
59025
+ deadband: 1
59026
+ },
59027
+ isMuted: { kind: "boolean" }
59028
+ } }
58783
59029
  };
58784
59030
  /**
58785
59031
  * mesh-network — collection cap for mesh-VPN providers.
@@ -60923,9 +61169,24 @@ var NpuInfoSchema = object({
60923
61169
  name: string().optional(),
60924
61170
  generation: _enum(["xdna1", "xdna2"]).optional()
60925
61171
  });
61172
+ var CoralBusSchema = _enum(["usb", "pci"]);
60926
61173
  var CoralInfoSchema = object({
60927
61174
  type: literal("coral-edgetpu"),
60928
- bus: string().optional()
61175
+ /** Legacy single-bus report (older nodes) — read via `coralUsableUnits`. */
61176
+ bus: string().optional(),
61177
+ /** Legacy USB unit count (older nodes) — read via `coralUsableUnits`. */
61178
+ count: number().int().nonnegative().optional(),
61179
+ /** Usable units per bus — each one is its own `edgetpu:<bus>[:N]` device. */
61180
+ units: array(object({
61181
+ bus: CoralBusSchema,
61182
+ count: number().int().nonnegative()
61183
+ })).readonly().optional(),
61184
+ /** Present-but-unusable units, each with its typed reason (never "absent"). */
61185
+ unavailable: array(object({
61186
+ bus: CoralBusSchema,
61187
+ count: number().int().nonnegative(),
61188
+ reason: _enum(["driver-missing", "device-not-accessible"])
61189
+ })).readonly().optional()
60929
61190
  });
60930
61191
  var HardwareInfoSchema = object({
60931
61192
  platform: HardwarePlatformSchema,
@@ -64072,9 +64333,29 @@ var streamParamsCapability = {
64072
64333
  */
64073
64334
  durability: "restored",
64074
64335
  /**
64075
- * History (D850): none — encoder configuration.
64336
+ * History (D850): the configured bitrate and frame rate of the main and sub
64337
+ * profiles. Configuration, so change-only on the default floor: a point is an
64338
+ * operator's (or a tuner's) edit, which is exactly what a chart of a stream's
64339
+ * quality over time must show.
64076
64340
  */
64077
- history: "none",
64341
+ history: { fields: {
64342
+ "main.bitrate": {
64343
+ kind: "gauge",
64344
+ unit: "kbps"
64345
+ },
64346
+ "main.framerate": {
64347
+ kind: "gauge",
64348
+ unit: "fps"
64349
+ },
64350
+ "sub.bitrate": {
64351
+ kind: "gauge",
64352
+ unit: "kbps"
64353
+ },
64354
+ "sub.framerate": {
64355
+ kind: "gauge",
64356
+ unit: "fps"
64357
+ }
64358
+ } },
64078
64359
  /** Clock fields: written, but excluded from the compare that decides
64079
64360
  * whether persisting is worth a SQLite commit. */
64080
64361
  volatileStateFields: ["lastFetchedAt"]
@@ -67252,6 +67533,15 @@ var BaseDevice = class {
67252
67533
  * Drivers can use the `getProbeFlags()` helper to read the flag bag
67253
67534
  * with a typed cast.
67254
67535
  *
67536
+ * Answer what you KNOW. A plain array is read as the complete list only
67537
+ * while this device is `online` and probed; return
67538
+ * `accessoryChildrenUnknown(reason)` whenever you cannot know the list right
67539
+ * now (no credentials, parent not connected, a failed or partial read) —
67540
+ * the kernel then deletes nothing. Return `accessoryChildrenComplete(list)`
67541
+ * to say "connected, and this is the complete list" explicitly. A shrink is
67542
+ * deleted only after a second agreeing complete read on a later probe (D49;
67543
+ * `packages/system/src/kernel/moleculer/accessory-prune-gate.ts`).
67544
+ *
67255
67545
  * Default: no children.
67256
67546
  */
67257
67547
  getAccessoryChildren() {
@@ -71383,7 +71673,19 @@ Object.freeze({
71383
71673
  addonId: null,
71384
71674
  access: "view"
71385
71675
  },
71386
- "logDestination.query": {
71676
+ "logDestination.cancelRead": {
71677
+ capName: "log-destination",
71678
+ capScope: "system",
71679
+ addonId: null,
71680
+ access: "create"
71681
+ },
71682
+ "logDestination.describeRead": {
71683
+ capName: "log-destination",
71684
+ capScope: "system",
71685
+ addonId: null,
71686
+ access: "view"
71687
+ },
71688
+ "logDestination.read": {
71387
71689
  capName: "log-destination",
71388
71690
  capScope: "system",
71389
71691
  addonId: null,
@@ -77390,6 +77692,11 @@ Object.freeze({
77390
77692
  form: "single",
77391
77693
  optional: false
77392
77694
  }],
77695
+ "logDestination.read": [{
77696
+ name: "deviceId",
77697
+ form: "single",
77698
+ optional: true
77699
+ }],
77393
77700
  "mediaPlayer.getStatus": [{
77394
77701
  name: "deviceId",
77395
77702
  form: "single",
package/dist/addon.mjs CHANGED
@@ -6233,7 +6233,7 @@ var ZodIssueCode = {
6233
6233
  var ZodFirstPartyTypeKind;
6234
6234
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
6235
6235
  //#endregion
6236
- //#region ../types/dist/sleep-yKL5gfrH.mjs
6236
+ //#region ../types/dist/sleep-BSuCCFjf.mjs
6237
6237
  /**
6238
6238
  * The audio chunk plane's byte format, and the ONE expansion from a coded
6239
6239
  * window to float samples (D455).
@@ -17813,7 +17813,19 @@ var DeviceHistorySubjectSchema = discriminatedUnion("kind", [object({
17813
17813
  kind: literal("node"),
17814
17814
  nodeId: string().min(1)
17815
17815
  })]);
17816
+ /**
17817
+ * `enum` stores a STATE as the ordinal of its value in the series' value list
17818
+ * (`DeviceHistorySeriesInfo.values`, append-only, so an ordinal never changes
17819
+ * meaning); a rollup keeps the time spent in each state (`states`).
17820
+ */
17816
17821
  var DeviceHistoryKindSchema = _enum([
17822
+ "gauge",
17823
+ "counter",
17824
+ "boolean",
17825
+ "enum"
17826
+ ]);
17827
+ /** What a PRODUCER may declare. `enum` is cap-only: its value list is the cap field's. */
17828
+ var DeviceHistoryProducerKindSchema = _enum([
17817
17829
  "gauge",
17818
17830
  "counter",
17819
17831
  "boolean"
@@ -17850,7 +17862,13 @@ var SeriesInfoSchema = object({
17850
17862
  /** `null` is unknown (a `unitFrom` series whose device does not state a unit right now), never a guess. */
17851
17863
  unit: string().nullable(),
17852
17864
  displayName: string(),
17853
- source: _enum(["cap", "addon"]),
17865
+ source: _enum([
17866
+ "cap",
17867
+ "addon",
17868
+ "derived"
17869
+ ]),
17870
+ /** `enum`: the value of each ordinal (index = ordinal); `null` for every other kind. */
17871
+ values: array(string()).readonly().nullable(),
17854
17872
  firstTs: number(),
17855
17873
  lastTs: number()
17856
17874
  });
@@ -17864,17 +17882,31 @@ var QueryPointSchema = object({
17864
17882
  twMean: number().nullable(),
17865
17883
  min: number(),
17866
17884
  max: number(),
17867
- /** `null` is unknown, never zero (D393). */
17868
- last: number().nullable()
17885
+ /** `null` is unknown, never zero (D393). For an `enum` series: the ordinal of {@link state}. */
17886
+ last: number().nullable(),
17887
+ /**
17888
+ * The increase over the point: a `counter`'s growth since the previous point
17889
+ * or bucket (a drop is a reset, counted from zero), and for
17890
+ * {@link DEVICE_HISTORY_ENERGY_KEY} the kWh used in the bucket. `null` for
17891
+ * every other kind, and when it cannot be known.
17892
+ */
17893
+ delta: number().nullable(),
17894
+ /** `enum`: the state in force at the end of the point (the name of `last`); `null` otherwise. */
17895
+ state: string().nullable(),
17896
+ /** `enum` rollup: milliseconds spent in each state inside the bucket; `null` for raw points and other kinds. */
17897
+ states: record(string(), number()).nullable()
17869
17898
  });
17870
17899
  var QuerySeriesSchema = object({
17871
17900
  scope: string(),
17872
17901
  /** The last point STRICTLY BEFORE `from` in the chosen tier, so a step chart can start at the held value. */
17873
17902
  before: object({
17874
17903
  t: number(),
17875
- value: number().nullable()
17904
+ value: number().nullable(),
17905
+ state: string().nullable()
17876
17906
  }).nullable(),
17877
- points: array(QueryPointSchema).readonly()
17907
+ points: array(QueryPointSchema).readonly(),
17908
+ /** A derived key: the stored key its points were computed from; `null` for a stored series. */
17909
+ derivedFrom: string().nullable()
17878
17910
  });
17879
17911
  /** The window part of a query, shared by the device and node forms. */
17880
17912
  var QueryWindowShape = {
@@ -17890,6 +17922,23 @@ var QueryResultSchema = object({
17890
17922
  series: array(QuerySeriesSchema).readonly(),
17891
17923
  truncated: boolean()
17892
17924
  });
17925
+ /** One read of a batch: a device's key or a node's key (exactly one subject). */
17926
+ var QueryManyItemSchema = union([object({
17927
+ deviceId: number().int(),
17928
+ key: string(),
17929
+ scope: string().optional()
17930
+ }), object({
17931
+ forNodeId: string().min(1),
17932
+ key: string(),
17933
+ scope: string().optional()
17934
+ })]);
17935
+ var QueryManyEntrySchema = discriminatedUnion("ok", [object({
17936
+ ok: literal(true),
17937
+ result: QueryResultSchema
17938
+ }), object({
17939
+ ok: literal(false),
17940
+ error: string()
17941
+ })]);
17893
17942
  var TierStatusSchema = object({
17894
17943
  tier: DeviceHistoryResolutionSchema,
17895
17944
  /** `null` until the first background count answered. */
@@ -17945,16 +17994,22 @@ var DeviceHistoryStatusSchema = object({
17945
17994
  lastRefreshAt: number().nullable()
17946
17995
  })
17947
17996
  });
17948
- method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly()), method(object({ nodeId: string().min(1) }), array(SeriesInfoSchema).readonly(), { auth: "admin" }), method(object({
17997
+ method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly()), method(object({ forNodeId: string().min(1) }), array(SeriesInfoSchema).readonly(), { auth: "admin" }), method(object({
17949
17998
  deviceId: number().int(),
17950
17999
  ...QueryWindowShape
17951
18000
  }), QueryResultSchema), method(object({
17952
- nodeId: string().min(1),
18001
+ forNodeId: string().min(1),
17953
18002
  ...QueryWindowShape
17954
18003
  }), QueryResultSchema, { auth: "admin" }), method(object({
18004
+ items: array(QueryManyItemSchema).min(1).max(24),
18005
+ from: QueryWindowShape.from,
18006
+ to: QueryWindowShape.to,
18007
+ resolution: QueryWindowShape.resolution,
18008
+ maxPoints: QueryWindowShape.maxPoints
18009
+ }), object({ results: array(QueryManyEntrySchema).readonly() }), { auth: "admin" }), method(object({
17955
18010
  name: string().regex(/^[a-z0-9-]+$/),
17956
18011
  subjectKind: _enum(["device", "node"]),
17957
- kind: DeviceHistoryKindSchema,
18012
+ kind: DeviceHistoryProducerKindSchema,
17958
18013
  unit: string().optional(),
17959
18014
  displayName: string().min(1),
17960
18015
  ingest: _enum(["points", "buckets"])
@@ -41180,14 +41235,106 @@ var LogEntrySchema = object({
41180
41235
  meta: record(string(), unknown()).optional(),
41181
41236
  tags: record(string(), string()).optional()
41182
41237
  });
41183
- method(LogEntrySchema, _void(), { kind: "mutation" }), method(object({
41184
- scope: array(string()).optional(),
41238
+ /**
41239
+ * A history READ against one destination (D898).
41240
+ *
41241
+ * Every filter is applied by the PROVIDER, before the limit — a filter the
41242
+ * browser applied after the limit is what made a rare device's lines
41243
+ * unreachable behind a busy one's. `before` / `after` are cursors the provider
41244
+ * minted (opaque to everyone else): a file position for the rotated files, a
41245
+ * nanosecond timestamp for Loki.
41246
+ *
41247
+ * A read is BOUNDED by `budgetMs`: a filter that matches nothing on a 30-day
41248
+ * store answers `done: false` with the cursor it reached and the bytes it
41249
+ * scanned, and the caller decides whether to go on. That is what makes a long
41250
+ * scan show progress and stop when asked — `cancelRead` ends the slice in
41251
+ * flight, and not asking for the next slice ends the scan.
41252
+ */
41253
+ var LogReadQuerySchema = object({
41254
+ /** Correlates `cancelRead`. Caller-chosen, unique per in-flight read. */
41255
+ requestId: string().min(1).max(64).optional(),
41256
+ /** The device the line is about (`tags.deviceId`, numeric). */
41257
+ deviceId: number().int().optional(),
41258
+ /**
41259
+ * The emitting addon — bare manifest id; `@<version>` / `::<sub>` suffixes
41260
+ * match. Not `addonId`: a cap router reads that name as "which provider".
41261
+ */
41262
+ fromAddonId: string().min(1).max(200).optional(),
41263
+ /**
41264
+ * The emitting node: matches the agent that emitted the line, the node
41265
+ * itself, or a worker under it (`<agent>/<runner>`) — the `agentId`
41266
+ * semantics of `matchesLogTags`. Not `nodeId`: a cap router reads that
41267
+ * name as "which node's provider".
41268
+ */
41269
+ fromNodeId: string().min(1).max(200).optional(),
41270
+ /** Any other tag, exact match (AND). */
41271
+ tags: record(string(), union([string(), number()])).optional(),
41272
+ /** Severity FLOOR: this level and above. */
41185
41273
  level: LogLevelSchema.optional(),
41186
- since: date().optional(),
41187
- until: date().optional(),
41188
- limit: number().optional(),
41189
- tags: record(string(), string()).optional()
41190
- }), array(LogEntrySchema).readonly());
41274
+ /** Case-insensitive substring over message, scope, tag values and meta values. */
41275
+ text: string().min(1).max(200).optional(),
41276
+ /** Epoch ms, inclusive. */
41277
+ since: number().optional(),
41278
+ /** Epoch ms, inclusive. */
41279
+ until: number().optional(),
41280
+ /** Older than this cursor (exclusive). Absent with `after` absent ⇒ from the newest. */
41281
+ before: string().min(1).max(1024).optional(),
41282
+ /** Newer than this cursor (exclusive). */
41283
+ after: string().min(1).max(1024).optional(),
41284
+ limit: number().int().min(1).max(1e3).optional(),
41285
+ /** Wall-clock bound of this slice. The provider caps it. */
41286
+ budgetMs: number().int().min(50).max(1e4).optional()
41287
+ });
41288
+ var LogReadResultSchema = object({
41289
+ /** Newest first. */
41290
+ entries: array(object({
41291
+ /** `<bootId>.<seq>` minted by the emitting LogManager — the dedupe key. */
41292
+ id: string().optional(),
41293
+ /** Epoch ms. */
41294
+ timestamp: number(),
41295
+ level: LogLevelSchema,
41296
+ scope: string().optional(),
41297
+ message: string(),
41298
+ tags: record(string(), union([string(), number()])).optional(),
41299
+ meta: record(string(), unknown()).optional()
41300
+ })),
41301
+ /** Pass as `before` for the next older page; null when nothing older exists. */
41302
+ nextBefore: string().nullable(),
41303
+ /** Pass as `after` to read what arrived since; null when unknown. */
41304
+ nextAfter: string().nullable(),
41305
+ /** Bytes this slice read (files) or received (remote). Progress, not a promise. */
41306
+ scannedBytes: number().int().nonnegative(),
41307
+ /**
41308
+ * True when the scan in this direction reached the end of the store.
41309
+ * False with fewer than `limit` entries means the budget ran out first —
41310
+ * call again with `nextBefore` to go on.
41311
+ */
41312
+ done: boolean(),
41313
+ /** True when `cancelRead` ended this slice early. */
41314
+ cancelled: boolean().optional()
41315
+ });
41316
+ var LogReadCapabilitiesSchema = object({
41317
+ /** False ⇒ this destination only ships lines (console, forwarder, an unconfigured Loki). */
41318
+ readable: boolean(),
41319
+ /** Why not, when `readable` is false — rendered next to the source. */
41320
+ reason: string().nullable(),
41321
+ /** Filters the provider applies itself. A false one is applied by nobody. */
41322
+ filters: object({
41323
+ deviceId: boolean(),
41324
+ addonId: boolean(),
41325
+ nodeId: boolean(),
41326
+ tags: boolean(),
41327
+ level: boolean(),
41328
+ text: boolean(),
41329
+ timeRange: boolean()
41330
+ }),
41331
+ /** How far back the store reaches, when the provider knows (days). */
41332
+ retentionDays: number().nullable()
41333
+ });
41334
+ 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() }), {
41335
+ kind: "mutation",
41336
+ auth: "admin"
41337
+ });
41191
41338
  /**
41192
41339
  * `login-method` — collection cap through which auth addons contribute
41193
41340
  * their pre-auth login surfaces to the login page. This is the SINGLE,
@@ -42905,9 +43052,11 @@ var alarmPanelCapability = {
42905
43052
  */
42906
43053
  durability: "restored",
42907
43054
  /**
42908
- * History (D850): none — enum state; arm/disarm history belongs in the events ledger.
43055
+ * History (D850): the panel's lifecycle state as an `enum` series —
43056
+ * change-only, no floor, so an `arming -> pending -> triggered` sequence of a
43057
+ * few seconds keeps every step. Who armed it stays in the events ledger.
42909
43058
  */
42910
- history: "none",
43059
+ history: { fields: { state: { kind: "enum" } } },
42911
43060
  /** Clock fields: written, but excluded from the compare that decides
42912
43061
  * whether persisting is worth a SQLite commit. */
42913
43062
  volatileStateFields: ["lastChangedAt"]
@@ -43785,6 +43934,33 @@ var NcRuleTargetSchema = object({
43785
43934
  params: record(string(), unknown()).optional()
43786
43935
  });
43787
43936
  /**
43937
+ * WHAT THE NOTIFICATION'S PICTURE IS (D897) — the ONE media choice of a rule.
43938
+ *
43939
+ * Every mode starts from the same CLEAN source frame of the trigger moment
43940
+ * (keyFrame → sceneFrame → lastSceneFrame, narrowed to the trigger instant and
43941
+ * to the zone that fired the rule) and renders it once at send time:
43942
+ * - `scene-boxes` — the whole scene, the subject outlined thick in the accent
43943
+ * colour and every OTHER track visible at that instant outlined thin, each
43944
+ * labelled with class and confidence ("dog 87%").
43945
+ * - `crop` — the subject cut out of that frame around its box at that instant.
43946
+ * - `clean` — the whole scene with nothing drawn on it.
43947
+ * - `none` — no picture.
43948
+ *
43949
+ * A mode that cannot be honoured (no box at that instant, a photograph with no
43950
+ * tracked subject) ships `clean` and names the reason in the log, per camera.
43951
+ * It replaces the `attach` × `frame` × `zoneCrop` triple, which let one rule
43952
+ * ship a crop on one event and a boxed scene on the next depending on which
43953
+ * stored kind had landed.
43954
+ */
43955
+ var NcMediaImageSchema = _enum([
43956
+ "scene-boxes",
43957
+ "crop",
43958
+ "clean",
43959
+ "none"
43960
+ ]);
43961
+ /**
43962
+ * @deprecated Read only by `normalizeNcMediaPolicy` (D897) — see {@link NcMediaImageSchema}.
43963
+ *
43788
43964
  * Media attachment policy (P1 still-image subset).
43789
43965
  * - `best` — the best AVAILABLE subject image at dispatch time (D-3).
43790
43966
  * - `best-matching` — the media that explains WHY the rule fired: a rule
@@ -43798,6 +43974,8 @@ var NcRuleTargetSchema = object({
43798
43974
  * - `none` — no attachment.
43799
43975
  */
43800
43976
  /**
43977
+ * @deprecated Read only by `normalizeNcMediaPolicy` (D897) — see {@link NcMediaImageSchema}.
43978
+ *
43801
43979
  * WHAT THE PICTURE SHOWS — chosen explicitly, because the implicit ladders
43802
43980
  * conflate it with the selection strategy and betray the request: asking for
43803
43981
  * the clean scene frame on an object-event owner used to start at
@@ -43826,16 +44004,29 @@ var NcMediaFrameSchema = _enum([
43826
44004
  */
43827
44005
  var NcLinkedCameraModeSchema = _enum(["mosaic", "each"]);
43828
44006
  var NcMediaPolicySchema = object({
44007
+ /**
44008
+ * The picture — see {@link NcMediaImageSchema}. Absent on a rule nobody has
44009
+ * saved since D897: `normalizeNcMediaPolicy` derives it from the legacy
44010
+ * triple below, at load and at every write, and the store keeps only this.
44011
+ */
44012
+ image: NcMediaImageSchema.optional(),
44013
+ /**
44014
+ * Draw the zone that FIRED the rule on the picture (`scene-boxes` / `clean`;
44015
+ * a `crop` never shows it). Valid only on a rule whose trigger is a zone —
44016
+ * `conditions.zones` or an occupancy zone — and refused on save otherwise.
44017
+ * Replaces `zoneCrop`.
44018
+ */
44019
+ showTriggerZone: boolean().optional(),
44020
+ /** @deprecated D897 — accepted from an editor that predates `image`, folded into it on save. */
43829
44021
  attach: _enum([
43830
44022
  "best",
43831
44023
  "best-matching",
43832
44024
  "keyFrame",
43833
44025
  "none"
43834
- ]).default("best"),
43835
- /** What the still shows. Absent = `cropped` (the historical `best` shape). */
44026
+ ]).optional(),
44027
+ /** @deprecated D897 — accepted from an editor that predates `image`, folded into it on save. */
43836
44028
  frame: NcMediaFrameSchema.optional(),
43837
- /** Crop the attached still to the rule's condition-zone bbox (padded) —
43838
- * "show me the ZONE", not the whole scene or the subject crop. */
44029
+ /** @deprecated D897 — folded into `image: 'clean'` + `showTriggerZone` on save. */
43839
44030
  zoneCrop: boolean().optional(),
43840
44031
  /**
43841
44032
  * Also attach a short GIF cut from the stream broker's clip ring around the
@@ -44007,7 +44198,9 @@ var NcRuleInputSchema = object({
44007
44198
  * targets.
44008
44199
  */
44009
44200
  targetUsers: array(string()).optional(),
44010
- media: NcMediaPolicySchema.default({ attach: "best" }),
44201
+ /** Absent = the kind's default picture (`resolveNcMediaImage`): the subject crop for a
44202
+ * detection, the clean scene for a sensor or a sound. Set explicitly on save (D897). */
44203
+ media: NcMediaPolicySchema.default({}),
44011
44204
  throttle: NcThrottleSchema.default({
44012
44205
  cooldownSec: 60,
44013
44206
  scope: "rule-device"
@@ -44944,13 +45137,37 @@ var NcAlarmModeOpeningsSchema = object({
44944
45137
  /** Covered devices whose state could not be read (D49): neither open nor closed. */
44945
45138
  unknown: array(number().int())
44946
45139
  });
45140
+ /**
45141
+ * One alarm INPUT — a (rule, device) pair — the operator bypassed until the
45142
+ * next disarm ("Bypass this input until disarm" on a trigger notification, or
45143
+ * `nc.bypassAlarmInput`). Reported so an armed alarm with a silenced input
45144
+ * never looks fully armed (D62: off must never look like broken).
45145
+ */
45146
+ var NcAlarmInputBypassViewSchema = object({
45147
+ ruleId: string(),
45148
+ /** The rule's current name (its frozen name when the rule is gone). */
45149
+ ruleName: string(),
45150
+ /** The input: the sensor of the match, else its camera. */
45151
+ deviceId: number().int(),
45152
+ /** The input's current name. */
45153
+ name: string(),
45154
+ /** When it was bypassed (ms epoch). */
45155
+ since: number(),
45156
+ /** Triggers from this input dropped since. */
45157
+ dropped: number().int().min(0)
45158
+ });
44947
45159
  var NcAlarmLiveSchema = object({
44948
45160
  state: AlarmStateSchema,
44949
45161
  /** The mode being armed into (exit delay) or held; null when disarmed. */
44950
45162
  targetMode: AlarmArmModeSchema.nullable(),
44951
45163
  availableModes: array(AlarmArmModeSchema),
44952
45164
  openings: array(NcAlarmModeOpeningsSchema),
44953
- exclusions: array(NcAlarmExclusionViewSchema)
45165
+ exclusions: array(NcAlarmExclusionViewSchema),
45166
+ /**
45167
+ * Inputs bypassed for the rest of this arm session; cleared on disarm.
45168
+ * Defaulted so an older hub answer still parses (as "none known").
45169
+ */
45170
+ bypassedInputs: array(NcAlarmInputBypassViewSchema).default([])
44954
45171
  });
44955
45172
  var NcAlarmConfigSchema = object({
44956
45173
  /**
@@ -55677,9 +55894,11 @@ var connectivityCapability = {
55677
55894
  */
55678
55895
  durability: "restored",
55679
55896
  /**
55680
- * History (D850): none — duplicates device-status.online (one authority for availability).
55897
+ * History (D850): `connected` as a boolean series — change-only, no floor. It
55898
+ * is the upstream entity's own link (a HA connectivity sensor), not the
55899
+ * device's reachability, which stays `device-status.online`.
55681
55900
  */
55682
- history: "none",
55901
+ history: { fields: { connected: { kind: "boolean" } } },
55683
55902
  /** Clock fields: written, but excluded from the compare that decides
55684
55903
  * whether persisting is worth a SQLite commit. */
55685
55904
  volatileStateFields: ["lastChangedAt"]
@@ -56503,11 +56722,22 @@ var dishwasherCapability = {
56503
56722
  },
56504
56723
  runtimeState: DishwasherStatusSchema,
56505
56724
  durability: "session",
56506
- history: { fields: { progressPercent: {
56507
- kind: "gauge",
56508
- unit: "%",
56509
- deadband: 2
56510
- } } }
56725
+ history: { fields: {
56726
+ progressPercent: {
56727
+ kind: "gauge",
56728
+ unit: "%",
56729
+ deadband: 2
56730
+ },
56731
+ state: { kind: "enum" },
56732
+ operationState: { kind: "enum" },
56733
+ remainingSeconds: {
56734
+ kind: "gauge",
56735
+ unit: "s",
56736
+ minIntervalMs: 6e4
56737
+ },
56738
+ doorOpen: { kind: "boolean" },
56739
+ powerOn: { kind: "boolean" }
56740
+ } }
56511
56741
  };
56512
56742
  var DoorbellStatusSchema = object({
56513
56743
  /** Ms epoch of the last press. null = never observed since this provider started. */
@@ -56624,9 +56854,15 @@ var enumSensorCapability = {
56624
56854
  */
56625
56855
  durability: "restored",
56626
56856
  /**
56627
- * History (D850): none — text/enum state has no history (non-goal).
56857
+ * History (D850): the value as an `enum` series (an appliance's program or
56858
+ * operation state, an HVAC action). The option set is per device, so the
56859
+ * value list is LEARNED as values are first seen (bounded). A sensor with a
56860
+ * `format` carries a timestamp, not a state, and is not recorded.
56628
56861
  */
56629
- history: "none",
56862
+ history: { fields: { value: {
56863
+ kind: "enum",
56864
+ skipWhenSet: "format"
56865
+ } } },
56630
56866
  /** Clock fields: written, but excluded from the compare that decides
56631
56867
  * whether persisting is worth a SQLite commit. */
56632
56868
  volatileStateFields: ["lastFetchedAt"]
@@ -58600,9 +58836,10 @@ var lockControlCapability = {
58600
58836
  */
58601
58837
  durability: "restored",
58602
58838
  /**
58603
- * History (D850): none — enum state; lock events belong in the events ledger.
58839
+ * History (D850): the lock's state as an `enum` series — change-only, no
58840
+ * floor: a jam or an unlock lasting seconds is the edge an operator looks for.
58604
58841
  */
58605
- history: "none",
58842
+ history: { fields: { state: { kind: "enum" } } },
58606
58843
  /** Clock fields: written, but excluded from the compare that decides
58607
58844
  * whether persisting is worth a SQLite commit. */
58608
58845
  volatileStateFields: ["lastChangedAt"]
@@ -58776,9 +59013,18 @@ var mediaPlayerCapability = {
58776
59013
  */
58777
59014
  durability: "session",
58778
59015
  /**
58779
- * History (D850): none — `positionMs` moves continuously while playing; volume is transient.
59016
+ * History (D850): volume (a level an operator or an automation sets; the
59017
+ * default 10 s floor folds a slider drag into its end value) and mute.
59018
+ * `positionMs` is not recorded: it moves continuously while playing.
58780
59019
  */
58781
- history: "none"
59020
+ history: { fields: {
59021
+ volumeLevel: {
59022
+ kind: "gauge",
59023
+ unit: "%",
59024
+ deadband: 1
59025
+ },
59026
+ isMuted: { kind: "boolean" }
59027
+ } }
58782
59028
  };
58783
59029
  /**
58784
59030
  * mesh-network — collection cap for mesh-VPN providers.
@@ -60922,9 +61168,24 @@ var NpuInfoSchema = object({
60922
61168
  name: string().optional(),
60923
61169
  generation: _enum(["xdna1", "xdna2"]).optional()
60924
61170
  });
61171
+ var CoralBusSchema = _enum(["usb", "pci"]);
60925
61172
  var CoralInfoSchema = object({
60926
61173
  type: literal("coral-edgetpu"),
60927
- bus: string().optional()
61174
+ /** Legacy single-bus report (older nodes) — read via `coralUsableUnits`. */
61175
+ bus: string().optional(),
61176
+ /** Legacy USB unit count (older nodes) — read via `coralUsableUnits`. */
61177
+ count: number().int().nonnegative().optional(),
61178
+ /** Usable units per bus — each one is its own `edgetpu:<bus>[:N]` device. */
61179
+ units: array(object({
61180
+ bus: CoralBusSchema,
61181
+ count: number().int().nonnegative()
61182
+ })).readonly().optional(),
61183
+ /** Present-but-unusable units, each with its typed reason (never "absent"). */
61184
+ unavailable: array(object({
61185
+ bus: CoralBusSchema,
61186
+ count: number().int().nonnegative(),
61187
+ reason: _enum(["driver-missing", "device-not-accessible"])
61188
+ })).readonly().optional()
60928
61189
  });
60929
61190
  var HardwareInfoSchema = object({
60930
61191
  platform: HardwarePlatformSchema,
@@ -64071,9 +64332,29 @@ var streamParamsCapability = {
64071
64332
  */
64072
64333
  durability: "restored",
64073
64334
  /**
64074
- * History (D850): none — encoder configuration.
64335
+ * History (D850): the configured bitrate and frame rate of the main and sub
64336
+ * profiles. Configuration, so change-only on the default floor: a point is an
64337
+ * operator's (or a tuner's) edit, which is exactly what a chart of a stream's
64338
+ * quality over time must show.
64075
64339
  */
64076
- history: "none",
64340
+ history: { fields: {
64341
+ "main.bitrate": {
64342
+ kind: "gauge",
64343
+ unit: "kbps"
64344
+ },
64345
+ "main.framerate": {
64346
+ kind: "gauge",
64347
+ unit: "fps"
64348
+ },
64349
+ "sub.bitrate": {
64350
+ kind: "gauge",
64351
+ unit: "kbps"
64352
+ },
64353
+ "sub.framerate": {
64354
+ kind: "gauge",
64355
+ unit: "fps"
64356
+ }
64357
+ } },
64077
64358
  /** Clock fields: written, but excluded from the compare that decides
64078
64359
  * whether persisting is worth a SQLite commit. */
64079
64360
  volatileStateFields: ["lastFetchedAt"]
@@ -67251,6 +67532,15 @@ var BaseDevice = class {
67251
67532
  * Drivers can use the `getProbeFlags()` helper to read the flag bag
67252
67533
  * with a typed cast.
67253
67534
  *
67535
+ * Answer what you KNOW. A plain array is read as the complete list only
67536
+ * while this device is `online` and probed; return
67537
+ * `accessoryChildrenUnknown(reason)` whenever you cannot know the list right
67538
+ * now (no credentials, parent not connected, a failed or partial read) —
67539
+ * the kernel then deletes nothing. Return `accessoryChildrenComplete(list)`
67540
+ * to say "connected, and this is the complete list" explicitly. A shrink is
67541
+ * deleted only after a second agreeing complete read on a later probe (D49;
67542
+ * `packages/system/src/kernel/moleculer/accessory-prune-gate.ts`).
67543
+ *
67254
67544
  * Default: no children.
67255
67545
  */
67256
67546
  getAccessoryChildren() {
@@ -71382,7 +71672,19 @@ Object.freeze({
71382
71672
  addonId: null,
71383
71673
  access: "view"
71384
71674
  },
71385
- "logDestination.query": {
71675
+ "logDestination.cancelRead": {
71676
+ capName: "log-destination",
71677
+ capScope: "system",
71678
+ addonId: null,
71679
+ access: "create"
71680
+ },
71681
+ "logDestination.describeRead": {
71682
+ capName: "log-destination",
71683
+ capScope: "system",
71684
+ addonId: null,
71685
+ access: "view"
71686
+ },
71687
+ "logDestination.read": {
71386
71688
  capName: "log-destination",
71387
71689
  capScope: "system",
71388
71690
  addonId: null,
@@ -77389,6 +77691,11 @@ Object.freeze({
77389
77691
  form: "single",
77390
77692
  optional: false
77391
77693
  }],
77694
+ "logDestination.read": [{
77695
+ name: "deviceId",
77696
+ form: "single",
77697
+ optional: true
77698
+ }],
77392
77699
  "mediaPlayer.getStatus": [{
77393
77700
  name: "deviceId",
77394
77701
  form: "single",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-tuya",
3
- "version": "0.2.130",
3
+ "version": "0.2.132",
4
4
  "description": "Tuya / Smart Life device-provider addon for CamStack — account-onboarded (Tuya IoT cloud fetch of device localKeys) + LOCAL DP control via the @apocaliss92/nodetuya encrypted-LAN client, exposing switch / water-heater-family kettle entities",
5
5
  "keywords": [
6
6
  "camstack",