@camstack/types 1.2.270 → 1.2.272

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 (52) hide show
  1. package/dist/addon.js +1 -1
  2. package/dist/addon.mjs +1 -1
  3. package/dist/capabilities/control.cap.d.ts +4 -4
  4. package/dist/capabilities/core-blocks.cap.d.ts +1 -1
  5. package/dist/capabilities/device-discovery.cap.d.ts +1 -1
  6. package/dist/capabilities/device-extension.cap.d.ts +8 -8
  7. package/dist/capabilities/device-manager.cap.d.ts +50 -0
  8. package/dist/capabilities/index.d.ts +2 -2
  9. package/dist/capabilities/integrations.cap.d.ts +3 -3
  10. package/dist/capabilities/llm-runtime.cap.d.ts +3 -3
  11. package/dist/capabilities/llm.cap.d.ts +4 -4
  12. package/dist/capabilities/motion.cap.d.ts +12 -0
  13. package/dist/capabilities/notification-rules.cap.d.ts +9 -9
  14. package/dist/capabilities/osd-manager.cap.d.ts +10 -10
  15. package/dist/capabilities/pet-feeder.cap.d.ts +4 -4
  16. package/dist/capabilities/pipeline-analytics.cap.d.ts +22 -10
  17. package/dist/capabilities/pipeline-executor.cap.d.ts +2 -2
  18. package/dist/capabilities/pipeline-orchestrator.cap.d.ts +156 -6
  19. package/dist/capabilities/pipeline-runner.cap.d.ts +9 -0
  20. package/dist/capabilities/recording-archive.cap.d.ts +4 -4
  21. package/dist/capabilities/recording-export.cap.d.ts +7 -7
  22. package/dist/capabilities/recording-onboard.cap.d.ts +5 -5
  23. package/dist/capabilities/recording.cap.d.ts +5 -5
  24. package/dist/capabilities/snapshot.cap.d.ts +2 -2
  25. package/dist/capabilities/storage-provider.cap.d.ts +11 -11
  26. package/dist/capabilities/storage.cap.d.ts +3 -3
  27. package/dist/capabilities/stream-broker.cap.d.ts +1 -1
  28. package/dist/capabilities/videoclips.cap.d.ts +3 -3
  29. package/dist/capabilities/zone-analytics.cap.d.ts +2 -2
  30. package/dist/composition/composition-report.d.ts +3 -3
  31. package/dist/{composition-D5BQywfe.mjs → composition-BK-GTFYb.mjs} +27 -3
  32. package/dist/{composition-BAH3n-zq.js → composition-BRxAnxtU.js} +27 -3
  33. package/dist/device/base-device-provider.d.ts +19 -1
  34. package/dist/device/device-context.d.ts +12 -0
  35. package/dist/expression/builtins.d.ts +18 -0
  36. package/dist/expression/expression-source.d.ts +2 -0
  37. package/dist/generated/addon-api.d.ts +7 -66
  38. package/dist/generated/device-proxy.d.ts +1 -1
  39. package/dist/generated/method-access-map.d.ts +1 -1
  40. package/dist/generated/method-device-selectors.d.ts +2 -2
  41. package/dist/index.d.ts +1 -0
  42. package/dist/index.js +299 -23
  43. package/dist/index.mjs +284 -24
  44. package/dist/interfaces/addon.d.ts +9 -0
  45. package/dist/interfaces/storage-location-mode.d.ts +1 -1
  46. package/dist/interfaces/storage-location.d.ts +1 -1
  47. package/dist/node.js +1 -1
  48. package/dist/node.mjs +1 -1
  49. package/dist/pipeline/camera-sensors.d.ts +146 -0
  50. package/dist/{sleep-Bg0IB7gg.js → sleep-DYGSsCgK.js} +1 -0
  51. package/dist/{sleep-E6eD4yQS.mjs → sleep-DlrgY4Qb.mjs} +1 -0
  52. package/package.json +1 -1
@@ -31,9 +31,9 @@ declare const BeginUploadInputSchema: z.ZodObject<{
31
31
  enabled: z.ZodOptional<z.ZodBoolean>;
32
32
  mode: z.ZodOptional<z.ZodEnum<{
33
33
  readonly: "readonly";
34
+ disabled: "disabled";
34
35
  active: "active";
35
36
  drain: "drain";
36
- disabled: "disabled";
37
37
  }>>;
38
38
  capacity: z.ZodOptional<z.ZodNullable<z.ZodObject<{
39
39
  totalBytes: z.ZodNumber;
@@ -75,9 +75,9 @@ declare const BeginDownloadInputSchema: z.ZodObject<{
75
75
  enabled: z.ZodOptional<z.ZodBoolean>;
76
76
  mode: z.ZodOptional<z.ZodEnum<{
77
77
  readonly: "readonly";
78
+ disabled: "disabled";
78
79
  active: "active";
79
80
  drain: "drain";
80
- disabled: "disabled";
81
81
  }>>;
82
82
  capacity: z.ZodOptional<z.ZodNullable<z.ZodObject<{
83
83
  totalBytes: z.ZodNumber;
@@ -180,9 +180,9 @@ export declare const storageProviderCapability: {
180
180
  enabled: z.ZodOptional<z.ZodBoolean>;
181
181
  mode: z.ZodOptional<z.ZodEnum<{
182
182
  readonly: "readonly";
183
+ disabled: "disabled";
183
184
  active: "active";
184
185
  drain: "drain";
185
- disabled: "disabled";
186
186
  }>>;
187
187
  capacity: z.ZodOptional<z.ZodNullable<z.ZodObject<{
188
188
  totalBytes: z.ZodNumber;
@@ -209,9 +209,9 @@ export declare const storageProviderCapability: {
209
209
  enabled: z.ZodOptional<z.ZodBoolean>;
210
210
  mode: z.ZodOptional<z.ZodEnum<{
211
211
  readonly: "readonly";
212
+ disabled: "disabled";
212
213
  active: "active";
213
214
  drain: "drain";
214
- disabled: "disabled";
215
215
  }>>;
216
216
  capacity: z.ZodOptional<z.ZodNullable<z.ZodObject<{
217
217
  totalBytes: z.ZodNumber;
@@ -239,9 +239,9 @@ export declare const storageProviderCapability: {
239
239
  enabled: z.ZodOptional<z.ZodBoolean>;
240
240
  mode: z.ZodOptional<z.ZodEnum<{
241
241
  readonly: "readonly";
242
+ disabled: "disabled";
242
243
  active: "active";
243
244
  drain: "drain";
244
- disabled: "disabled";
245
245
  }>>;
246
246
  capacity: z.ZodOptional<z.ZodNullable<z.ZodObject<{
247
247
  totalBytes: z.ZodNumber;
@@ -268,9 +268,9 @@ export declare const storageProviderCapability: {
268
268
  enabled: z.ZodOptional<z.ZodBoolean>;
269
269
  mode: z.ZodOptional<z.ZodEnum<{
270
270
  readonly: "readonly";
271
+ disabled: "disabled";
271
272
  active: "active";
272
273
  drain: "drain";
273
- disabled: "disabled";
274
274
  }>>;
275
275
  capacity: z.ZodOptional<z.ZodNullable<z.ZodObject<{
276
276
  totalBytes: z.ZodNumber;
@@ -297,9 +297,9 @@ export declare const storageProviderCapability: {
297
297
  enabled: z.ZodOptional<z.ZodBoolean>;
298
298
  mode: z.ZodOptional<z.ZodEnum<{
299
299
  readonly: "readonly";
300
+ disabled: "disabled";
300
301
  active: "active";
301
302
  drain: "drain";
302
- disabled: "disabled";
303
303
  }>>;
304
304
  capacity: z.ZodOptional<z.ZodNullable<z.ZodObject<{
305
305
  totalBytes: z.ZodNumber;
@@ -326,9 +326,9 @@ export declare const storageProviderCapability: {
326
326
  enabled: z.ZodOptional<z.ZodBoolean>;
327
327
  mode: z.ZodOptional<z.ZodEnum<{
328
328
  readonly: "readonly";
329
+ disabled: "disabled";
329
330
  active: "active";
330
331
  drain: "drain";
331
- disabled: "disabled";
332
332
  }>>;
333
333
  capacity: z.ZodOptional<z.ZodNullable<z.ZodObject<{
334
334
  totalBytes: z.ZodNumber;
@@ -355,9 +355,9 @@ export declare const storageProviderCapability: {
355
355
  enabled: z.ZodOptional<z.ZodBoolean>;
356
356
  mode: z.ZodOptional<z.ZodEnum<{
357
357
  readonly: "readonly";
358
+ disabled: "disabled";
358
359
  active: "active";
359
360
  drain: "drain";
360
- disabled: "disabled";
361
361
  }>>;
362
362
  capacity: z.ZodOptional<z.ZodNullable<z.ZodObject<{
363
363
  totalBytes: z.ZodNumber;
@@ -383,9 +383,9 @@ export declare const storageProviderCapability: {
383
383
  enabled: z.ZodOptional<z.ZodBoolean>;
384
384
  mode: z.ZodOptional<z.ZodEnum<{
385
385
  readonly: "readonly";
386
+ disabled: "disabled";
386
387
  active: "active";
387
388
  drain: "drain";
388
- disabled: "disabled";
389
389
  }>>;
390
390
  capacity: z.ZodOptional<z.ZodNullable<z.ZodObject<{
391
391
  totalBytes: z.ZodNumber;
@@ -426,9 +426,9 @@ export declare const storageProviderCapability: {
426
426
  enabled: z.ZodOptional<z.ZodBoolean>;
427
427
  mode: z.ZodOptional<z.ZodEnum<{
428
428
  readonly: "readonly";
429
+ disabled: "disabled";
429
430
  active: "active";
430
431
  drain: "drain";
431
- disabled: "disabled";
432
432
  }>>;
433
433
  capacity: z.ZodOptional<z.ZodNullable<z.ZodObject<{
434
434
  totalBytes: z.ZodNumber;
@@ -98,9 +98,9 @@ export declare const storageCapability: {
98
98
  enabled: z.ZodOptional<z.ZodBoolean>;
99
99
  mode: z.ZodOptional<z.ZodEnum<{
100
100
  readonly: "readonly";
101
+ disabled: "disabled";
101
102
  active: "active";
102
103
  drain: "drain";
103
- disabled: "disabled";
104
104
  }>>;
105
105
  capacity: z.ZodOptional<z.ZodNullable<z.ZodObject<{
106
106
  totalBytes: z.ZodNumber;
@@ -138,9 +138,9 @@ export declare const storageCapability: {
138
138
  nodeId: z.ZodOptional<z.ZodString>;
139
139
  mode: z.ZodOptional<z.ZodEnum<{
140
140
  readonly: "readonly";
141
+ disabled: "disabled";
141
142
  active: "active";
142
143
  drain: "drain";
143
- disabled: "disabled";
144
144
  }>>;
145
145
  enabled: z.ZodOptional<z.ZodBoolean>;
146
146
  displayName: z.ZodString;
@@ -166,9 +166,9 @@ export declare const storageCapability: {
166
166
  enabled: z.ZodOptional<z.ZodBoolean>;
167
167
  mode: z.ZodOptional<z.ZodEnum<{
168
168
  readonly: "readonly";
169
+ disabled: "disabled";
169
170
  active: "active";
170
171
  drain: "drain";
171
- disabled: "disabled";
172
172
  }>>;
173
173
  capacity: z.ZodOptional<z.ZodNullable<z.ZodObject<{
174
174
  totalBytes: z.ZodNumber;
@@ -294,10 +294,10 @@ export type BrokerDecodedClient = z.infer<typeof BrokerDecodedClientSchema>;
294
294
  export type BrokerAudioClient = z.infer<typeof BrokerAudioClientSchema>;
295
295
  export type BrokerClients = z.infer<typeof BrokerClientsSchema>;
296
296
  export declare const PlaceholderReasonSchema: z.ZodEnum<{
297
+ offline: "offline";
297
298
  disabled: "disabled";
298
299
  sleeping: "sleeping";
299
300
  reconnecting: "reconnecting";
300
- offline: "offline";
301
301
  waking: "waking";
302
302
  }>;
303
303
  export type PlaceholderReason = z.infer<typeof PlaceholderReasonSchema>;
@@ -61,9 +61,9 @@ export declare const MAX_CLIP_LABELS = 3;
61
61
  * rendered as `Refused: <prose>`.
62
62
  */
63
63
  export declare const ClipStillRefusalCodeSchema: z.ZodEnum<{
64
+ unsupported: "unsupported";
64
65
  "unknown-device": "unknown-device";
65
66
  sleeping: "sleeping";
66
- unsupported: "unsupported";
67
67
  "camera-refused": "camera-refused";
68
68
  "no-keyframe": "no-keyframe";
69
69
  "queue-full": "queue-full";
@@ -155,8 +155,8 @@ export declare const ClipSchema: z.ZodObject<{
155
155
  thumbnailMint: z.ZodOptional<z.ZodString>;
156
156
  thumbnailUnavailable: z.ZodOptional<z.ZodObject<{
157
157
  reason: z.ZodEnum<{
158
- sleeping: "sleeping";
159
158
  unsupported: "unsupported";
159
+ sleeping: "sleeping";
160
160
  "camera-refused": "camera-refused";
161
161
  "no-keyframe": "no-keyframe";
162
162
  }>;
@@ -627,8 +627,8 @@ export declare const videoclipsCapability: {
627
627
  thumbnailMint: z.ZodOptional<z.ZodString>;
628
628
  thumbnailUnavailable: z.ZodOptional<z.ZodObject<{
629
629
  reason: z.ZodEnum<{
630
- sleeping: "sleeping";
631
630
  unsupported: "unsupported";
631
+ sleeping: "sleeping";
632
632
  "camera-refused": "camera-refused";
633
633
  "no-keyframe": "no-keyframe";
634
634
  }>;
@@ -122,8 +122,8 @@ export type CameraOccupancySnapshot = z.infer<typeof CameraOccupancySnapshotSche
122
122
  export declare const CameraOccupancySnapshotForDeviceSchema: z.ZodObject<{
123
123
  deviceId: z.ZodNumber;
124
124
  read: z.ZodEnum<{
125
- read: "read";
126
125
  unreadable: "unreadable";
126
+ read: "read";
127
127
  }>;
128
128
  snapshot: z.ZodNullable<z.ZodObject<{
129
129
  ts: z.ZodNumber;
@@ -310,8 +310,8 @@ export declare const zoneAnalyticsCapability: {
310
310
  }, z.core.$strip>, z.ZodReadonly<z.ZodArray<z.ZodObject<{
311
311
  deviceId: z.ZodNumber;
312
312
  read: z.ZodEnum<{
313
- read: "read";
314
313
  unreadable: "unreadable";
314
+ read: "read";
315
315
  }>;
316
316
  snapshot: z.ZodNullable<z.ZodObject<{
317
317
  ts: z.ZodNumber;
@@ -171,8 +171,8 @@ export declare function compositionFieldKey(plan: Pick<CompositionFieldPlan, 'ca
171
171
  * `replace`s named fields of one it has natively.
172
172
  */
173
173
  export declare const CompositionFeatureModeSchema: z.ZodEnum<{
174
- new: "new";
175
174
  replace: "replace";
175
+ new: "new";
176
176
  add: "add";
177
177
  }>;
178
178
  export type CompositionFeatureMode = z.infer<typeof CompositionFeatureModeSchema>;
@@ -180,8 +180,8 @@ export declare const CompositionFeaturePlanSchema: z.ZodObject<{
180
180
  featureIndex: z.ZodNumber;
181
181
  cap: z.ZodString;
182
182
  mode: z.ZodEnum<{
183
- new: "new";
184
183
  replace: "replace";
184
+ new: "new";
185
185
  add: "add";
186
186
  }>;
187
187
  }, z.core.$strip>;
@@ -285,8 +285,8 @@ export declare const CompositionValidationSchema: z.ZodObject<{
285
285
  featureIndex: z.ZodNumber;
286
286
  cap: z.ZodString;
287
287
  mode: z.ZodEnum<{
288
- new: "new";
289
288
  replace: "replace";
289
+ new: "new";
290
290
  add: "add";
291
291
  }>;
292
292
  }, z.core.$strip>>;
@@ -989,14 +989,37 @@ function evaluateRose(level, changedAt, debounceMs, call, field, env) {
989
989
  field.acceptedEdgeAt = verdict.timestamp;
990
990
  return verdict.timestamp;
991
991
  }
992
+ /**
993
+ * `count(x)`: how many times `x` strictly advanced (D670). It starts on the
994
+ * first ANSWERED read of `x`:
995
+ * - an answered `null` ("never happened") primes it with no high-water, so the
996
+ * next finite value is a real advance and counts 1;
997
+ * - an answered finite value primes it with that value as the high-water and
998
+ * no increment — it is history, not an event;
999
+ * - anything else (a read that did not answer reaches here as neither) does
1000
+ * NOT prime it (D393: unknown is not null).
1001
+ * An unavailable binding never reaches this function at all: the field is
1002
+ * judged unavailable before the expression runs.
1003
+ *
1004
+ * Edge case, accepted: an input that answers `null` and LATER reports a
1005
+ * historical value (a sensor's `lastChangedAt` that was null until its first
1006
+ * report) counts that value once. For the doorbell it cannot happen — its
1007
+ * input is its own `lastPressedAt`, which only advances on a `rose` edge that
1008
+ * also emits the press — but an external input can overcount by one.
1009
+ */
992
1010
  function evaluateCount(input, call, currentOutput) {
993
1011
  const currentCount = typeof currentOutput === "number" && Number.isFinite(currentOutput) && currentOutput >= 0 ? currentOutput : 0;
1012
+ if (input === null) {
1013
+ call.primed = true;
1014
+ return currentCount;
1015
+ }
994
1016
  if (typeof input !== "number" || !Number.isFinite(input)) return currentCount;
995
- if (call.highWater === null) {
1017
+ if (!call.primed) {
1018
+ call.primed = true;
996
1019
  call.highWater = input;
997
1020
  return currentCount;
998
1021
  }
999
- if (input <= call.highWater) return currentCount;
1022
+ if (call.highWater !== null && input <= call.highWater) return currentCount;
1000
1023
  call.highWater = input;
1001
1024
  return currentCount + 1;
1002
1025
  }
@@ -1744,7 +1767,8 @@ function evaluateStatefulExpressionCall(invocation, memory, env) {
1744
1767
  case "count": {
1745
1768
  const call = existing?.kind === "count" ? existing : {
1746
1769
  kind: "count",
1747
- highWater: null
1770
+ highWater: null,
1771
+ primed: false
1748
1772
  };
1749
1773
  memory.calls.set(invocation.path, call);
1750
1774
  return evaluateCount(invocation.args[0], call, env.currentOutput);
@@ -989,14 +989,37 @@ function evaluateRose(level, changedAt, debounceMs, call, field, env) {
989
989
  field.acceptedEdgeAt = verdict.timestamp;
990
990
  return verdict.timestamp;
991
991
  }
992
+ /**
993
+ * `count(x)`: how many times `x` strictly advanced (D670). It starts on the
994
+ * first ANSWERED read of `x`:
995
+ * - an answered `null` ("never happened") primes it with no high-water, so the
996
+ * next finite value is a real advance and counts 1;
997
+ * - an answered finite value primes it with that value as the high-water and
998
+ * no increment — it is history, not an event;
999
+ * - anything else (a read that did not answer reaches here as neither) does
1000
+ * NOT prime it (D393: unknown is not null).
1001
+ * An unavailable binding never reaches this function at all: the field is
1002
+ * judged unavailable before the expression runs.
1003
+ *
1004
+ * Edge case, accepted: an input that answers `null` and LATER reports a
1005
+ * historical value (a sensor's `lastChangedAt` that was null until its first
1006
+ * report) counts that value once. For the doorbell it cannot happen — its
1007
+ * input is its own `lastPressedAt`, which only advances on a `rose` edge that
1008
+ * also emits the press — but an external input can overcount by one.
1009
+ */
992
1010
  function evaluateCount(input, call, currentOutput) {
993
1011
  const currentCount = typeof currentOutput === "number" && Number.isFinite(currentOutput) && currentOutput >= 0 ? currentOutput : 0;
1012
+ if (input === null) {
1013
+ call.primed = true;
1014
+ return currentCount;
1015
+ }
994
1016
  if (typeof input !== "number" || !Number.isFinite(input)) return currentCount;
995
- if (call.highWater === null) {
1017
+ if (!call.primed) {
1018
+ call.primed = true;
996
1019
  call.highWater = input;
997
1020
  return currentCount;
998
1021
  }
999
- if (input <= call.highWater) return currentCount;
1022
+ if (call.highWater !== null && input <= call.highWater) return currentCount;
1000
1023
  call.highWater = input;
1001
1024
  return currentCount + 1;
1002
1025
  }
@@ -1744,7 +1767,8 @@ function evaluateStatefulExpressionCall(invocation, memory, env) {
1744
1767
  case "count": {
1745
1768
  const call = existing?.kind === "count" ? existing : {
1746
1769
  kind: "count",
1747
- highWater: null
1770
+ highWater: null,
1771
+ primed: false
1748
1772
  };
1749
1773
  memory.calls.set(invocation.path, call);
1750
1774
  return evaluateCount(invocation.args[0], call, env.currentOutput);
@@ -176,8 +176,13 @@ export declare abstract class BaseDeviceProvider<TConfig extends object = Record
176
176
  /** Retry lane width. See `device-restore-retry.ts` for why retries
177
177
  * never re-stampede full-width while the initial pass does (D167). */
178
178
  protected readonly restoreRetryConcurrency: number;
179
- private _restoreRetryScheduler;
179
+ /** Every bounded retry this process started — the default pass's, and each
180
+ * `restoreWithBoundedRetry` of a provider's own rows. Cancelled together. */
181
+ private _restoreRetrySchedulers;
180
182
  private _restoreRetryCompletion;
183
+ /** Set by `onShutdown` BEFORE the retries are cancelled: a restore pass still
184
+ * in flight must not start a scheduler after the cancel ran. */
185
+ private _restoreShuttingDown;
181
186
  private readonly _permanentRestoreFailures;
182
187
  /** Settles when the background retry rounds finish (or `null` when
183
188
  * nothing failed). Exposed for tests and subclass diagnostics —
@@ -215,6 +220,19 @@ export declare abstract class BaseDeviceProvider<TConfig extends object = Record
215
220
  private cancelRestoreRetries;
216
221
  private recordPermanentRestoreFailure;
217
222
  private scheduleRestoreRetries;
223
+ /**
224
+ * Restore rows the default pass does not handle (a provider's own restore
225
+ * loop) under the SAME bounded retry (D347): one attempt each, in order; a
226
+ * row that throws is logged with `tags.deviceId` and retried in the
227
+ * background rounds, then marked permanently failed like any other.
228
+ *
229
+ * A restore is a device build, and a build whose runtime-state load did not
230
+ * answer is REFUSED rather than started on cold defaults (D677) — so a
231
+ * transient hub read must cost a retry, never the device until the next
232
+ * runner restart. An ANSWERED `{}` is the device's true state and never
233
+ * refuses.
234
+ */
235
+ protected restoreWithBoundedRetry(rows: readonly SavedDevice[], attempt: (saved: SavedDevice) => Promise<void>): Promise<void>;
218
236
  /**
219
237
  * Tear down and reconstruct ONE device from its persisted rows — the
220
238
  * `deviceProvider.reloadDevice` cap method. Persistence is never touched,
@@ -162,6 +162,18 @@ export interface DeviceManagerApi {
162
162
  * don't need to think about this — the standard `create()` shortcut
163
163
  * loads it automatically. */
164
164
  createContext(stableId: string, id: number, parentDeviceId?: number | null, persistedConfig?: Record<string, unknown>): DeviceContext;
165
+ /** `createContext` for a device the context will BUILD, hydrated like
166
+ * `create()`: the device's stored runtime state is loaded first. A load
167
+ * that did not answer REJECTS — a device built on an empty state writes
168
+ * its cold-start defaults over the restored values (D677). A brand-new
169
+ * device's `{}` is an answer, never a refusal.
170
+ *
171
+ * `createContext` stays synchronous and EMPTY-state for callers that build
172
+ * no device from it (a composer graft registers method-serving natives
173
+ * only) and for addons compiled before this method existed. Optional: an
174
+ * older kernel does not provide it — a caller falls back to
175
+ * `createContext` there. */
176
+ loadContext?(stableId: string, id: number, parentDeviceId?: number | null, persistedConfig?: Record<string, unknown>): Promise<DeviceContext>;
165
177
  /** Read the per-device persisted config blob from the DB. Returns
166
178
  * `{}` for devices that have no persisted row yet (newly allocated
167
179
  * but not registered). Used by callers going through the manual
@@ -48,6 +48,24 @@ export declare function evaluateRose(level: unknown, changedAt: unknown, debounc
48
48
  readonly startedAtMs: number;
49
49
  readonly nowMs: number;
50
50
  }): number | null;
51
+ /**
52
+ * `count(x)`: how many times `x` strictly advanced (D670). It starts on the
53
+ * first ANSWERED read of `x`:
54
+ * - an answered `null` ("never happened") primes it with no high-water, so the
55
+ * next finite value is a real advance and counts 1;
56
+ * - an answered finite value primes it with that value as the high-water and
57
+ * no increment — it is history, not an event;
58
+ * - anything else (a read that did not answer reaches here as neither) does
59
+ * NOT prime it (D393: unknown is not null).
60
+ * An unavailable binding never reaches this function at all: the field is
61
+ * judged unavailable before the expression runs.
62
+ *
63
+ * Edge case, accepted: an input that answers `null` and LATER reports a
64
+ * historical value (a sensor's `lastChangedAt` that was null until its first
65
+ * report) counts that value once. For the doorbell it cannot happen — its
66
+ * input is its own `lastPressedAt`, which only advances on a `rose` edge that
67
+ * also emits the press — but an external input can overcount by one.
68
+ */
51
69
  export declare function evaluateCount(input: unknown, call: CountCallState, currentOutput: unknown): number;
52
70
  /** Frozen, null-prototype builtin table. */
53
71
  export declare const EXPRESSION_BUILTINS: Readonly<Record<string, ExpressionBuiltin>>;
@@ -17,6 +17,8 @@ export interface RoseCallState {
17
17
  export interface CountCallState {
18
18
  readonly kind: 'count';
19
19
  highWater: number | null;
20
+ /** Whether a read has ANSWERED yet (a finite value or `null`); `highWater` means nothing before. */
21
+ primed: boolean;
20
22
  }
21
23
  export type StatefulCallState = RoseCallState | CountCallState;
22
24
  export interface StatefulExpressionMemory {
@@ -2623,6 +2623,13 @@ export type AppRouter = TrpcCoreRouter<{
2623
2623
  output: z.infer<typeof deviceManagerCapability.methods.setWrapperActive.output>;
2624
2624
  meta: object;
2625
2625
  }>;
2626
+ getWrapperActivation: TRPCQueryProcedure<{
2627
+ input: {
2628
+ [x: string]: unknown;
2629
+ } & z.input<typeof deviceManagerCapability.methods.getWrapperActivation.input>;
2630
+ output: z.infer<typeof deviceManagerCapability.methods.getWrapperActivation.output>;
2631
+ meta: object;
2632
+ }>;
2626
2633
  listWrappersForCap: TRPCQueryProcedure<{
2627
2634
  input: {
2628
2635
  [x: string]: unknown;
@@ -9621,39 +9628,6 @@ export type AppRouter = TrpcCoreRouter<{
9621
9628
  output: Record<string, unknown>;
9622
9629
  meta: object;
9623
9630
  }>;
9624
- updateGlobal: import("@trpc/server").TRPCMutationProcedure<{
9625
- input: {
9626
- addonId: string;
9627
- field: string;
9628
- value: unknown;
9629
- };
9630
- output: {
9631
- success: true;
9632
- };
9633
- meta: object;
9634
- }>;
9635
- updateDevice: import("@trpc/server").TRPCMutationProcedure<{
9636
- input: {
9637
- addonId: string;
9638
- deviceId: string;
9639
- field: string;
9640
- value: unknown;
9641
- };
9642
- output: {
9643
- success: true;
9644
- };
9645
- meta: object;
9646
- }>;
9647
- replaceGlobal: import("@trpc/server").TRPCMutationProcedure<{
9648
- input: {
9649
- addonId: string;
9650
- config: Record<string, unknown>;
9651
- };
9652
- output: {
9653
- success: true;
9654
- };
9655
- meta: object;
9656
- }>;
9657
9631
  }>> & import("@trpc/server").TRPCDecorateCreateRouterOptions<{
9658
9632
  getGlobal: import("@trpc/server").TRPCQueryProcedure<{
9659
9633
  input: {
@@ -9670,39 +9644,6 @@ export type AppRouter = TrpcCoreRouter<{
9670
9644
  output: Record<string, unknown>;
9671
9645
  meta: object;
9672
9646
  }>;
9673
- updateGlobal: import("@trpc/server").TRPCMutationProcedure<{
9674
- input: {
9675
- addonId: string;
9676
- field: string;
9677
- value: unknown;
9678
- };
9679
- output: {
9680
- success: true;
9681
- };
9682
- meta: object;
9683
- }>;
9684
- updateDevice: import("@trpc/server").TRPCMutationProcedure<{
9685
- input: {
9686
- addonId: string;
9687
- deviceId: string;
9688
- field: string;
9689
- value: unknown;
9690
- };
9691
- output: {
9692
- success: true;
9693
- };
9694
- meta: object;
9695
- }>;
9696
- replaceGlobal: import("@trpc/server").TRPCMutationProcedure<{
9697
- input: {
9698
- addonId: string;
9699
- config: Record<string, unknown>;
9700
- };
9701
- output: {
9702
- success: true;
9703
- };
9704
- meta: object;
9705
- }>;
9706
9647
  }>;
9707
9648
  eventBusProxy: import("@trpc/server/unstable-core-do-not-import").Router<{
9708
9649
  ctx: any;
@@ -293,7 +293,7 @@ export interface DeviceProxy {
293
293
  readonly audioAnalyzer: Pick<InferDeviceProxyCap<typeof audioAnalyzerCapability>, 'detachDevice'>;
294
294
  readonly deviceAdoption: Pick<InferDeviceProxyCap<typeof deviceAdoptionCapability>, 'getStatus'>;
295
295
  readonly deviceExport: Pick<InferDeviceProxyCap<typeof deviceExportCapability>, 'getDeviceSettingsContribution' | 'getDeviceLiveContribution' | 'applyDeviceSettingsPatch'>;
296
- readonly deviceManager: Pick<InferDeviceProxyCap<typeof deviceManagerCapability>, 'loadConfig' | 'loadRuntimeState' | 'loadMeta' | 'setName' | 'setLocation' | 'setType' | 'setIntegrationId' | 'setLinkDeviceId' | 'setPrimaryChildEntityId' | 'setChildLayout' | 'setDisplay' | 'getWireableFields' | 'setRole' | 'applyInitialMeta' | 'setMetadata' | 'setDisabled' | 'getDevice' | 'getLinkedDevices' | 'getStreamSources' | 'getConfigSchema' | 'getSettingsSchema' | 'updateConfig' | 'enable' | 'disable' | 'remove' | 'getStreamProfileMap' | 'setStreamProfileMap' | 'probeStreams' | 'getBindings' | 'setWrapperActive' | 'getDeviceSettingsAggregate' | 'getDeviceLiveInfoAggregate' | 'getDeviceAggregate' | 'runDeviceAction' | 'updateDeviceField' | 'updateDeviceFieldsBatch' | 'testField' | 'getDeviceStatusAggregate'>;
296
+ readonly deviceManager: Pick<InferDeviceProxyCap<typeof deviceManagerCapability>, 'loadConfig' | 'loadRuntimeState' | 'loadMeta' | 'setName' | 'setLocation' | 'setType' | 'setIntegrationId' | 'setLinkDeviceId' | 'setPrimaryChildEntityId' | 'setChildLayout' | 'setDisplay' | 'getWireableFields' | 'setRole' | 'applyInitialMeta' | 'setMetadata' | 'setDisabled' | 'getDevice' | 'getLinkedDevices' | 'getStreamSources' | 'getConfigSchema' | 'getSettingsSchema' | 'updateConfig' | 'enable' | 'disable' | 'remove' | 'getStreamProfileMap' | 'setStreamProfileMap' | 'probeStreams' | 'getBindings' | 'setWrapperActive' | 'getWrapperActivation' | 'getDeviceSettingsAggregate' | 'getDeviceLiveInfoAggregate' | 'getDeviceAggregate' | 'runDeviceAction' | 'updateDeviceField' | 'updateDeviceFieldsBatch' | 'testField' | 'getDeviceStatusAggregate'>;
297
297
  readonly deviceState: Pick<InferDeviceProxyCap<typeof deviceStateCapability>, 'getSnapshot' | 'getCapSlice' | 'setCapSlice' | 'claimFields' | 'patchOwnedFields' | 'releaseClaim' | 'getNativeCapSlice'>;
298
298
  readonly faceGallery: Pick<InferDeviceProxyCap<typeof faceGalleryCapability>, 'listRecentFaces' | 'getFaceByTrack'>;
299
299
  readonly networkQuality: Pick<InferDeviceProxyCap<typeof networkQualityCapability>, 'getDeviceStats' | 'reportClientStats'>;
@@ -6,7 +6,7 @@
6
6
  * scope+access check inside `protectedProcedure` (see
7
7
  * `server/backend/src/api/trpc/trpc.middleware.ts`).
8
8
  *
9
- * Coverage: 1191 method paths across 162 capabilities.
9
+ * Coverage: 1192 method paths across 162 capabilities.
10
10
  */
11
11
  import type { CapabilityMethodAccess } from '../capabilities/capability-definition.js';
12
12
  export interface MethodAccessRecord {
@@ -6,8 +6,8 @@
6
6
  * system-scope cap that takes a deviceId was previously never device-filtered
7
7
  * — see the generator header).
8
8
  *
9
- * Coverage: 403 methods carry a device reference, of which
10
- * 142 are on SYSTEM-scope caps.
9
+ * Coverage: 404 methods carry a device reference, of which
10
+ * 143 are on SYSTEM-scope caps.
11
11
  *
12
12
  * Top-level fields, number arrays, and one-level arrays of objects carrying
13
13
  * a numeric device field (targets[].deviceId) are all mapped; the matcher
package/dist/index.d.ts CHANGED
@@ -243,6 +243,7 @@ export { NC_SERVER_PACKAGE_NAME, NC_UPDATE_EVENT_PACKAGE_NAMES, type NcInstalled
243
243
  export type { TimelapseCadencePair, TimelapsePreviewMode, TimelapseRule, TimelapseRuleInput, TimelapseRulePatch, TimelapseTemplate, } from './notification/timelapse-rule.js';
244
244
  export { assertTimelapseCadences, DEFAULT_TIMELAPSE_PREVIEW_TEXT, readTimelapseGeneratedAt, TIMELAPSE_DENSE_FLOOR_SEC, TimelapseRuleInputSchema, TimelapseRulePatchSchema, TimelapseRuleSchema, TimelapseTemplateSchema, } from './notification/timelapse-rule.js';
245
245
  export { CLUSTER_MODEL_SCOPED_STEPS, CLUSTER_MODEL_SECTION_ID, CLUSTER_STEP_SETTING_FIELDS, type ClusterModelScopedStep, type ClusterStepModels, type ClusterStepSettingField, type ClusterStepSettings, clusterModelSettingKey, clusterStepSettingFieldsFor, clusterStepSettingKey, DEFAULT_CLUSTER_STEP_MODELS, DEFAULT_CLUSTER_STEP_SETTINGS, DEFAULT_MIN_LANDMARK_FACE_SIZE_PX, type HydratedClusterSection, type HydratedClusterView, interpretStoredClusterModel, type InvalidClusterStepModelEntry, invalidClusterStepModelEntries, isClusterScopedStep, overlayClusterStepSettings, pickClusterStepModels, pickClusterStepSettings, pickInvalidClusterStepModels, readClusterStepModels, readClusterStepSettings, resolveClusterStepModelId, type StepModelScope, type StoredClusterModelInterpretation, } from './pipeline/cluster-model-scope.js';
246
+ export { CAMERA_SENSORS_NOT_LOADED, CAMERA_SENSORS_SETTINGS_KEY, CAMERA_TRIGGER, type CameraSensorAttachment, CameraSensorAttachmentSchema, type CameraSensorRef, CameraSensorRefSchema, cameraSensorRefKey, type CameraSensorsConfig, CameraSensorsConfigSchema, type CameraSensorsMode, CameraSensorsModeSchema, type CameraSensorsNotForwarded, CameraSensorsNotForwardedSchema, type CameraSensorsStatus, CameraSensorsStatusSchema, MAX_CAMERA_SENSORS, type MotionTriggeredBy, type MotionTriggeredByReading, MotionTriggeredBySchema, readMotionTriggeredBy, } from './pipeline/camera-sensors.js';
246
247
  export { type FormatRunnableModel, stepModelRunsOnFormat, } from './pipeline/step-format-runnable.js';
247
248
  export { DEFAULT_DETAIL_CROP_CONVENTION, DETAIL_CROP_PADDING_FIELD, DETAIL_CROP_PADDING_KEY, DETAIL_CROP_SECTION_ID, DETAIL_CROP_SQUARE_KEY, type DetailCropConvention, DetailCropConventionSchema, type DetailCropRect, deriveDetailCropRect, FULL_IMAGE_BBOX, type HydratedSettingsSection, type HydratedSettingsView, pickDetailCropConvention, readDetailCropConvention, } from './pipeline/detail-crop.js';
248
249
  export { DEFAULT_NATIVE_LEASE_SETTINGS, NATIVE_LEASE_ACTIVITY_FIELD, NATIVE_LEASE_ACTIVITY_KEY, NATIVE_LEASE_ADMISSION_FIELD, NATIVE_LEASE_ADMISSION_KEY, NATIVE_LEASE_BUDGET_FIELD, NATIVE_LEASE_BUDGET_KEY, NATIVE_LEASE_HOLD_FIELD, NATIVE_LEASE_HOLD_KEY, NATIVE_LEASE_SCENE_BUDGET_FIELD, NATIVE_LEASE_SCENE_BUDGET_KEY, NATIVE_LEASE_SECTION_ID, NATIVE_LEASE_TILE_BUDGET_FIELD, NATIVE_LEASE_TILE_BUDGET_KEY, type NativeLeaseAdmission, NativeLeaseAdmissionSchema, type NativeLeaseKnob, type NativeLeaseNumberKnob, type NativeLeaseSettings, type NativeLeaseSettingsOverride, NativeLeaseSettingsSchema, pickNativeLeaseOverride, readNativeLeaseOverride, } from './pipeline/native-lease.js';