@camstack/types 1.2.404 → 1.2.406

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 (58) hide show
  1. package/dist/addon.js +21 -2
  2. package/dist/addon.mjs +21 -2
  3. package/dist/capabilities/index.d.ts +6 -3
  4. package/dist/capabilities/notification-rules.cap.d.ts +3 -78
  5. package/dist/capabilities/osd-manager.cap.d.ts +0 -18
  6. package/dist/capabilities/pipeline-analytics.cap.d.ts +24 -0
  7. package/dist/capabilities/pipeline-orchestrator.cap.d.ts +36 -0
  8. package/dist/capabilities/platform-probe.cap.d.ts +34 -0
  9. package/dist/capabilities/running-state.cap.d.ts +76 -0
  10. package/dist/capabilities/schemas/package-llm-verdict.d.ts +14 -0
  11. package/dist/capabilities/schemas/zone-rule.d.ts +4 -0
  12. package/dist/capabilities/zone-rules.cap.d.ts +10 -0
  13. package/dist/client.js +10 -62
  14. package/dist/client.mjs +10 -62
  15. package/dist/{composition-eoYYVfOp.js → composition-RmnnN39T.js} +86 -2
  16. package/dist/{composition-CB6PMT9p.mjs → composition-xz-ud5EQ.mjs} +86 -2
  17. package/dist/device/cap-vocabulary/entries/appliances.d.ts +1 -1
  18. package/dist/enums/event-category.d.ts +4 -0
  19. package/dist/enums.js +1 -1
  20. package/dist/enums.mjs +1 -1
  21. package/dist/{event-category-fDPduoeC.mjs → event-category-Ceif8n-v.mjs} +4 -0
  22. package/dist/{event-category-CXrwjC3e.js → event-category-DG6Vir8Z.js} +4 -0
  23. package/dist/expression/builtins.d.ts +7 -18
  24. package/dist/expression/expression-source.d.ts +14 -2
  25. package/dist/generated/addon-api.d.ts +14 -0
  26. package/dist/generated/addon-cap-facts.d.ts +1 -1
  27. package/dist/generated/cap-status-types.d.ts +3 -1
  28. package/dist/generated/capability-router-map.d.ts +5 -2
  29. package/dist/generated/device-local-state.d.ts +3 -0
  30. package/dist/generated/device-proxy.d.ts +3 -0
  31. package/dist/generated/device-scoped-caps.d.ts +1 -1
  32. package/dist/generated/history-catalog.d.ts +1 -1
  33. package/dist/generated/method-access-map.d.ts +1 -1
  34. package/dist/generated/method-device-selectors.d.ts +1 -1
  35. package/dist/generated/runtime-state-durability.d.ts +1 -1
  36. package/dist/index.d.ts +4 -0
  37. package/dist/index.js +2534 -1415
  38. package/dist/index.mjs +2471 -1415
  39. package/dist/interfaces/config-ui.d.ts +69 -2
  40. package/dist/interfaces/platform.d.ts +7 -0
  41. package/dist/node-color.d.ts +1 -1
  42. package/dist/node.js +1 -1
  43. package/dist/node.mjs +1 -1
  44. package/dist/pipeline/auto-tune/accelerator-compute.d.ts +116 -0
  45. package/dist/pipeline/auto-tune/detector-performance.d.ts +5 -0
  46. package/dist/pipeline/auto-tune/hardware-class.d.ts +5 -4
  47. package/dist/pipeline/auto-tune/index.d.ts +1 -0
  48. package/dist/pipeline/auto-tune/plan-schemas.d.ts +100 -0
  49. package/dist/pipeline/auto-tune/recommend.d.ts +31 -9
  50. package/dist/pipeline/second-pass/index.d.ts +2 -0
  51. package/dist/pipeline/second-pass/motion-crop-plan.d.ts +183 -0
  52. package/dist/pipeline/second-pass/small-subject-recovery.d.ts +216 -0
  53. package/dist/running-state/assignment.d.ts +34 -0
  54. package/dist/running-state/defaults.d.ts +3 -0
  55. package/dist/running-state/from-operation.d.ts +14 -0
  56. package/dist/{sleep-CHIEEJkY.mjs → sleep-CYfIZzGv.mjs} +7 -3
  57. package/dist/{sleep-BKS4OPMo.js → sleep-UP964hNP.js} +7 -3
  58. package/package.json +1 -1
@@ -1138,7 +1138,7 @@ var ExpressionEvalError = class extends Error {
1138
1138
  //#endregion
1139
1139
  //#region src/expression/builtins.ts
1140
1140
  function isStatefulBuiltin(name) {
1141
- return name === "rose" || name === "count";
1141
+ return name === "rose" || name === "count" || name === "dwell" || name === "latchedAt";
1142
1142
  }
1143
1143
  function asFiniteNumber(value, name, index) {
1144
1144
  if (typeof value !== "number" || !Number.isFinite(value)) throw new ExpressionEvalError(`${name}: argument ${index + 1} must be a finite number`);
@@ -1229,6 +1229,57 @@ function disarmRoseMemory(memory) {
1229
1229
  * input is its own `lastPressedAt`, which only advances on a `rose` edge that
1230
1230
  * also emits the press — but an external input can overcount by one.
1231
1231
  */
1232
+ function asNonNegativeMs(value, name, index) {
1233
+ const ms = asFiniteNumber(value, name, index);
1234
+ if (ms < 0) throw new ExpressionEvalError(`${name}: delay must be a non-negative finite number`);
1235
+ return ms;
1236
+ }
1237
+ /**
1238
+ * `dwell(active, onForMs, offForMs)`: unknown until a delay elapses, then holds
1239
+ * the latched boolean through gaps shorter than the opposing delay (D933).
1240
+ */
1241
+ function evaluateDwell(activeRaw, onForMsRaw, offForMsRaw, call, nowMs, hooks) {
1242
+ const active = asBoolean(activeRaw, "dwell", 0);
1243
+ const onForMs = asNonNegativeMs(onForMsRaw, "dwell", 1);
1244
+ const offForMs = asNonNegativeMs(offForMsRaw, "dwell", 2);
1245
+ if (call.latched === null) {
1246
+ if (call.seenSince === null) call.seenSince = nowMs;
1247
+ const delay = active ? onForMs : offForMs;
1248
+ if (nowMs - call.seenSince >= delay) {
1249
+ call.latched = active;
1250
+ return call.latched;
1251
+ }
1252
+ hooks?.noteDeadline?.(call.seenSince + delay);
1253
+ return null;
1254
+ }
1255
+ if (active === call.latched) {
1256
+ call.pendingSince = null;
1257
+ return call.latched;
1258
+ }
1259
+ if (call.pendingSince === null) call.pendingSince = nowMs;
1260
+ const delay = active ? onForMs : offForMs;
1261
+ if (nowMs - call.pendingSince >= delay) {
1262
+ call.latched = active;
1263
+ call.pendingSince = null;
1264
+ return call.latched;
1265
+ }
1266
+ hooks?.noteDeadline?.(call.pendingSince + delay);
1267
+ return call.latched;
1268
+ }
1269
+ /** `latchedAt(value)`: epoch ms when `value` last changed; null clears the stamp. */
1270
+ function evaluateLatchedAt(value, call, nowMs) {
1271
+ if (value === null) {
1272
+ call.last = null;
1273
+ call.at = null;
1274
+ return null;
1275
+ }
1276
+ if (typeof value !== "boolean" && typeof value !== "number" && typeof value !== "string") return call.at;
1277
+ if (call.last !== value) {
1278
+ call.last = value;
1279
+ call.at = nowMs;
1280
+ }
1281
+ return call.at;
1282
+ }
1232
1283
  function evaluateCount(input, call, currentOutput) {
1233
1284
  const currentCount = typeof currentOutput === "number" && Number.isFinite(currentOutput) && currentOutput >= 0 ? currentOutput : 0;
1234
1285
  if (input === null) {
@@ -1398,6 +1449,20 @@ var table = {
1398
1449
  apply: () => {
1399
1450
  throw new ExpressionEvalError("count: stateful evaluation context is required");
1400
1451
  }
1452
+ },
1453
+ dwell: {
1454
+ minArgs: 3,
1455
+ maxArgs: 3,
1456
+ apply: () => {
1457
+ throw new ExpressionEvalError("dwell: stateful evaluation context is required");
1458
+ }
1459
+ },
1460
+ latchedAt: {
1461
+ minArgs: 1,
1462
+ maxArgs: 1,
1463
+ apply: () => {
1464
+ throw new ExpressionEvalError("latchedAt: stateful evaluation context is required");
1465
+ }
1401
1466
  }
1402
1467
  };
1403
1468
  /** Frozen, null-prototype builtin table. */
@@ -1975,7 +2040,7 @@ function cloneStatefulExpressionMemory(memory) {
1975
2040
  disarmRoseNext: memory.disarmRoseNext
1976
2041
  };
1977
2042
  }
1978
- function evaluateStatefulExpressionCall(invocation, memory, env) {
2043
+ function evaluateStatefulExpressionCall(invocation, memory, env, hooks) {
1979
2044
  const existing = memory.calls.get(invocation.path);
1980
2045
  switch (invocation.name) {
1981
2046
  case "rose": {
@@ -1997,6 +2062,25 @@ function evaluateStatefulExpressionCall(invocation, memory, env) {
1997
2062
  memory.calls.set(invocation.path, call);
1998
2063
  return evaluateCount(invocation.args[0], call, env.currentOutput);
1999
2064
  }
2065
+ case "dwell": {
2066
+ const call = existing?.kind === "dwell" ? existing : {
2067
+ kind: "dwell",
2068
+ pendingSince: null,
2069
+ latched: null,
2070
+ seenSince: null
2071
+ };
2072
+ memory.calls.set(invocation.path, call);
2073
+ return evaluateDwell(invocation.args[0], invocation.args[1], invocation.args[2], call, env.nowMs, hooks);
2074
+ }
2075
+ case "latchedAt": {
2076
+ const call = existing?.kind === "latchedAt" ? existing : {
2077
+ kind: "latchedAt",
2078
+ last: void 0,
2079
+ at: null
2080
+ };
2081
+ memory.calls.set(invocation.path, call);
2082
+ return evaluateLatchedAt(invocation.args[0], call, env.nowMs);
2083
+ }
2000
2084
  }
2001
2085
  }
2002
2086
  /** The `now` epoch-ms binding is auto-injected into every evaluation and is a
@@ -1138,7 +1138,7 @@ var ExpressionEvalError = class extends Error {
1138
1138
  //#endregion
1139
1139
  //#region src/expression/builtins.ts
1140
1140
  function isStatefulBuiltin(name) {
1141
- return name === "rose" || name === "count";
1141
+ return name === "rose" || name === "count" || name === "dwell" || name === "latchedAt";
1142
1142
  }
1143
1143
  function asFiniteNumber(value, name, index) {
1144
1144
  if (typeof value !== "number" || !Number.isFinite(value)) throw new ExpressionEvalError(`${name}: argument ${index + 1} must be a finite number`);
@@ -1229,6 +1229,57 @@ function disarmRoseMemory(memory) {
1229
1229
  * input is its own `lastPressedAt`, which only advances on a `rose` edge that
1230
1230
  * also emits the press — but an external input can overcount by one.
1231
1231
  */
1232
+ function asNonNegativeMs(value, name, index) {
1233
+ const ms = asFiniteNumber(value, name, index);
1234
+ if (ms < 0) throw new ExpressionEvalError(`${name}: delay must be a non-negative finite number`);
1235
+ return ms;
1236
+ }
1237
+ /**
1238
+ * `dwell(active, onForMs, offForMs)`: unknown until a delay elapses, then holds
1239
+ * the latched boolean through gaps shorter than the opposing delay (D933).
1240
+ */
1241
+ function evaluateDwell(activeRaw, onForMsRaw, offForMsRaw, call, nowMs, hooks) {
1242
+ const active = asBoolean(activeRaw, "dwell", 0);
1243
+ const onForMs = asNonNegativeMs(onForMsRaw, "dwell", 1);
1244
+ const offForMs = asNonNegativeMs(offForMsRaw, "dwell", 2);
1245
+ if (call.latched === null) {
1246
+ if (call.seenSince === null) call.seenSince = nowMs;
1247
+ const delay = active ? onForMs : offForMs;
1248
+ if (nowMs - call.seenSince >= delay) {
1249
+ call.latched = active;
1250
+ return call.latched;
1251
+ }
1252
+ hooks?.noteDeadline?.(call.seenSince + delay);
1253
+ return null;
1254
+ }
1255
+ if (active === call.latched) {
1256
+ call.pendingSince = null;
1257
+ return call.latched;
1258
+ }
1259
+ if (call.pendingSince === null) call.pendingSince = nowMs;
1260
+ const delay = active ? onForMs : offForMs;
1261
+ if (nowMs - call.pendingSince >= delay) {
1262
+ call.latched = active;
1263
+ call.pendingSince = null;
1264
+ return call.latched;
1265
+ }
1266
+ hooks?.noteDeadline?.(call.pendingSince + delay);
1267
+ return call.latched;
1268
+ }
1269
+ /** `latchedAt(value)`: epoch ms when `value` last changed; null clears the stamp. */
1270
+ function evaluateLatchedAt(value, call, nowMs) {
1271
+ if (value === null) {
1272
+ call.last = null;
1273
+ call.at = null;
1274
+ return null;
1275
+ }
1276
+ if (typeof value !== "boolean" && typeof value !== "number" && typeof value !== "string") return call.at;
1277
+ if (call.last !== value) {
1278
+ call.last = value;
1279
+ call.at = nowMs;
1280
+ }
1281
+ return call.at;
1282
+ }
1232
1283
  function evaluateCount(input, call, currentOutput) {
1233
1284
  const currentCount = typeof currentOutput === "number" && Number.isFinite(currentOutput) && currentOutput >= 0 ? currentOutput : 0;
1234
1285
  if (input === null) {
@@ -1398,6 +1449,20 @@ var table = {
1398
1449
  apply: () => {
1399
1450
  throw new ExpressionEvalError("count: stateful evaluation context is required");
1400
1451
  }
1452
+ },
1453
+ dwell: {
1454
+ minArgs: 3,
1455
+ maxArgs: 3,
1456
+ apply: () => {
1457
+ throw new ExpressionEvalError("dwell: stateful evaluation context is required");
1458
+ }
1459
+ },
1460
+ latchedAt: {
1461
+ minArgs: 1,
1462
+ maxArgs: 1,
1463
+ apply: () => {
1464
+ throw new ExpressionEvalError("latchedAt: stateful evaluation context is required");
1465
+ }
1401
1466
  }
1402
1467
  };
1403
1468
  /** Frozen, null-prototype builtin table. */
@@ -1975,7 +2040,7 @@ function cloneStatefulExpressionMemory(memory) {
1975
2040
  disarmRoseNext: memory.disarmRoseNext
1976
2041
  };
1977
2042
  }
1978
- function evaluateStatefulExpressionCall(invocation, memory, env) {
2043
+ function evaluateStatefulExpressionCall(invocation, memory, env, hooks) {
1979
2044
  const existing = memory.calls.get(invocation.path);
1980
2045
  switch (invocation.name) {
1981
2046
  case "rose": {
@@ -1997,6 +2062,25 @@ function evaluateStatefulExpressionCall(invocation, memory, env) {
1997
2062
  memory.calls.set(invocation.path, call);
1998
2063
  return evaluateCount(invocation.args[0], call, env.currentOutput);
1999
2064
  }
2065
+ case "dwell": {
2066
+ const call = existing?.kind === "dwell" ? existing : {
2067
+ kind: "dwell",
2068
+ pendingSince: null,
2069
+ latched: null,
2070
+ seenSince: null
2071
+ };
2072
+ memory.calls.set(invocation.path, call);
2073
+ return evaluateDwell(invocation.args[0], invocation.args[1], invocation.args[2], call, env.nowMs, hooks);
2074
+ }
2075
+ case "latchedAt": {
2076
+ const call = existing?.kind === "latchedAt" ? existing : {
2077
+ kind: "latchedAt",
2078
+ last: void 0,
2079
+ at: null
2080
+ };
2081
+ memory.calls.set(invocation.path, call);
2082
+ return evaluateLatchedAt(invocation.args[0], call, env.nowMs);
2083
+ }
2000
2084
  }
2001
2085
  }
2002
2086
  /** The `now` epoch-ms binding is auto-injected into every evaluation and is a
@@ -1,5 +1,5 @@
1
1
  import type { CapVocabularySlice } from '../types.js';
2
- type ApplianceCap = 'vacuum-control' | 'lawn-mower-control' | 'dishwasher' | 'pet-feeder' | 'media-player' | 'consumables' | 'navigation' | 'script-runner' | 'automation-control' | 'notifier' | 'update';
2
+ type ApplianceCap = 'vacuum-control' | 'lawn-mower-control' | 'dishwasher' | 'pet-feeder' | 'media-player' | 'consumables' | 'running-state' | 'navigation' | 'script-runner' | 'automation-control' | 'notifier' | 'update';
3
3
  /** The appliance family of the vocabulary. */
4
4
  export declare const APPLIANCE_CAP_VOCABULARY: CapVocabularySlice<ApplianceCap>;
5
5
  export {};
@@ -469,6 +469,10 @@ export declare enum EventCategory {
469
469
  * on the device detail page.
470
470
  */
471
471
  DoorbellOnPressed = "doorbell.onPressed",
472
+ /** Mirrors `runningStateCapability.events.onStarted`. */
473
+ RunningStarted = "running.started",
474
+ /** Mirrors `runningStateCapability.events.onFinished`. */
475
+ RunningFinished = "running.finished",
472
476
  /**
473
477
  * Cap event fired by every device that registers the `event-emitter`
474
478
  * capability. Mirrors `eventEmitterCapability.events.onEvent`. Carries
package/dist/enums.js CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_event_category = require("./event-category-CXrwjC3e.js");
2
+ const require_event_category = require("./event-category-DG6Vir8Z.js");
3
3
  //#region src/enums/event-source-type.ts
4
4
  var EventSourceType = /* @__PURE__ */ function(EventSourceType) {
5
5
  EventSourceType["Addon"] = "addon";
package/dist/enums.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as EventCategory } from "./event-category-fDPduoeC.mjs";
1
+ import { t as EventCategory } from "./event-category-Ceif8n-v.mjs";
2
2
  //#region src/enums/event-source-type.ts
3
3
  var EventSourceType = /* @__PURE__ */ function(EventSourceType) {
4
4
  EventSourceType["Addon"] = "addon";
@@ -470,6 +470,10 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
470
470
  * on the device detail page.
471
471
  */
472
472
  EventCategory["DoorbellOnPressed"] = "doorbell.onPressed";
473
+ /** Mirrors `runningStateCapability.events.onStarted`. */
474
+ EventCategory["RunningStarted"] = "running.started";
475
+ /** Mirrors `runningStateCapability.events.onFinished`. */
476
+ EventCategory["RunningFinished"] = "running.finished";
473
477
  /**
474
478
  * Cap event fired by every device that registers the `event-emitter`
475
479
  * capability. Mirrors `eventEmitterCapability.events.onEvent`. Carries
@@ -470,6 +470,10 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
470
470
  * on the device detail page.
471
471
  */
472
472
  EventCategory["DoorbellOnPressed"] = "doorbell.onPressed";
473
+ /** Mirrors `runningStateCapability.events.onStarted`. */
474
+ EventCategory["RunningStarted"] = "running.started";
475
+ /** Mirrors `runningStateCapability.events.onFinished`. */
476
+ EventCategory["RunningFinished"] = "running.finished";
473
477
  /**
474
478
  * Cap event fired by every device that registers the `event-emitter`
475
479
  * capability. Mirrors `eventEmitterCapability.events.onEvent`. Carries
@@ -16,7 +16,7 @@
16
16
  * closed rather than emitting a garbage value.
17
17
  */
18
18
  import type { ExpressionValue } from './ast.js';
19
- import type { CountCallState, RoseCallState, StatefulExpressionMemory } from './expression-source.js';
19
+ import type { CountCallState, DwellCallState, LatchedAtCallState, RoseCallState, StatefulExpressionMemory } from './expression-source.js';
20
20
  /** Optional runtime hooks the evaluator threads through to builtins. */
21
21
  export interface ExpressionEvalHooks {
22
22
  /** Convert `value` from unit `from` to unit `to`; `null` when the pair is
@@ -41,7 +41,7 @@ export interface ExpressionBuiltin {
41
41
  readonly maxArgs: number;
42
42
  readonly apply: (args: readonly ExpressionValue[], hooks: ExpressionEvalHooks) => ExpressionValue;
43
43
  }
44
- export type StatefulExpressionBuiltin = 'rose' | 'count';
44
+ export type StatefulExpressionBuiltin = 'rose' | 'count' | 'dwell' | 'latchedAt';
45
45
  export declare function isStatefulBuiltin(name: string): name is StatefulExpressionBuiltin;
46
46
  export declare function evaluateRose(level: unknown, changedAt: unknown, debounceMs: unknown, call: RoseCallState, field: StatefulExpressionMemory, env: {
47
47
  readonly currentOutput: number | null;
@@ -51,23 +51,12 @@ export declare function evaluateRose(level: unknown, changedAt: unknown, debounc
51
51
  /** Next evaluation of every `rose` call baselines without rising. */
52
52
  export declare function disarmRoseMemory(memory: StatefulExpressionMemory): void;
53
53
  /**
54
- * `count(x)`: how many times `x` strictly advanced (D670). It starts on the
55
- * first ANSWERED read of `x`:
56
- * - an answered `null` ("never happened") primes it with no high-water, so the
57
- * next finite value is a real advance and counts 1;
58
- * - an answered finite value primes it with that value as the high-water and
59
- * no increment — it is history, not an event;
60
- * - anything else (a read that did not answer reaches here as neither) does
61
- * NOT prime it (D393: unknown is not null).
62
- * An unavailable binding never reaches this function at all: the field is
63
- * judged unavailable before the expression runs.
64
- *
65
- * Edge case, accepted: an input that answers `null` and LATER reports a
66
- * historical value (a sensor's `lastChangedAt` that was null until its first
67
- * report) counts that value once. For the doorbell it cannot happen — its
68
- * input is its own `lastPressedAt`, which only advances on a `rose` edge that
69
- * also emits the press — but an external input can overcount by one.
54
+ * `dwell(active, onForMs, offForMs)`: unknown until a delay elapses, then holds
55
+ * the latched boolean through gaps shorter than the opposing delay (D933).
70
56
  */
57
+ export declare function evaluateDwell(activeRaw: unknown, onForMsRaw: unknown, offForMsRaw: unknown, call: DwellCallState, nowMs: number, hooks?: ExpressionEvalHooks): boolean | null;
58
+ /** `latchedAt(value)`: epoch ms when `value` last changed; null clears the stamp. */
59
+ export declare function evaluateLatchedAt(value: unknown, call: LatchedAtCallState, nowMs: number): number | null;
71
60
  export declare function evaluateCount(input: unknown, call: CountCallState, currentOutput: unknown): number;
72
61
  /** Frozen, null-prototype builtin table. */
73
62
  export declare const EXPRESSION_BUILTINS: Readonly<Record<string, ExpressionBuiltin>>;
@@ -9,6 +9,7 @@
9
9
  * positions (derive a value, gate a trigger, compute an argument).
10
10
  */
11
11
  import type { ExpressionValue } from './ast.js';
12
+ import { type ExpressionEvalHooks } from './builtins.js';
12
13
  import { type ExpressionEvalOptions, type StatefulCallInvocation } from './evaluator.js';
13
14
  export interface RoseCallState {
14
15
  readonly kind: 'rose';
@@ -27,7 +28,18 @@ export interface CountCallState {
27
28
  /** Whether a read has ANSWERED yet (a finite value or `null`); `highWater` means nothing before. */
28
29
  primed: boolean;
29
30
  }
30
- export type StatefulCallState = RoseCallState | CountCallState;
31
+ export interface DwellCallState {
32
+ readonly kind: 'dwell';
33
+ pendingSince: number | null;
34
+ latched: boolean | null;
35
+ seenSince: number | null;
36
+ }
37
+ export interface LatchedAtCallState {
38
+ readonly kind: 'latchedAt';
39
+ last: ExpressionValue | undefined;
40
+ at: number | null;
41
+ }
42
+ export type StatefulCallState = RoseCallState | CountCallState | DwellCallState | LatchedAtCallState;
31
43
  export interface StatefulExpressionMemory {
32
44
  readonly calls: Map<string, StatefulCallState>;
33
45
  acceptedEdgeAt: number | null;
@@ -44,7 +56,7 @@ export interface StatefulExpressionEnvironment {
44
56
  readonly startedAtMs: number;
45
57
  readonly nowMs: number;
46
58
  }
47
- export declare function evaluateStatefulExpressionCall(invocation: StatefulCallInvocation, memory: StatefulExpressionMemory, env: StatefulExpressionEnvironment): ExpressionValue;
59
+ export declare function evaluateStatefulExpressionCall(invocation: StatefulCallInvocation, memory: StatefulExpressionMemory, env: StatefulExpressionEnvironment, hooks?: ExpressionEvalHooks): ExpressionValue;
48
60
  /** The `now` epoch-ms binding is auto-injected into every evaluation and is a
49
61
  * reserved binding name (authors may not rebind it). */
50
62
  export declare const EXPRESSION_INJECTED_NOW = "now";
@@ -8541,6 +8541,20 @@ export type AppRouter = TrpcCoreRouter<{
8541
8541
  meta: object;
8542
8542
  }>;
8543
8543
  }>>;
8544
+ runningState: TRPCBuiltRouter<{
8545
+ ctx: TrpcContext;
8546
+ meta: object;
8547
+ errorShape: AugmentedErrorShape;
8548
+ transformer: true;
8549
+ }, TRPCDecorateCreateRouterOptions<{
8550
+ getStatus: TRPCQueryProcedure<{
8551
+ input: {
8552
+ [x: string]: unknown;
8553
+ } & z.input<typeof DEVICE_STATUS_METHOD.getStatus.input>;
8554
+ output: z.infer<typeof DEVICE_STATUS_METHOD.getStatus.output>;
8555
+ meta: object;
8556
+ }>;
8557
+ }>>;
8544
8558
  sceneMonitor: TRPCBuiltRouter<{
8545
8559
  ctx: TrpcContext;
8546
8560
  meta: object;
@@ -5,7 +5,7 @@
5
5
  * `ALL_CAPABILITY_DEFINITIONS` (the whole Zod schema graph, ~+100 MB heap per
6
6
  * runner). See docs/decisions/adr-0028.md.
7
7
  *
8
- * Coverage: 1 advance-derived caps, 73 caps with 363 state leaves.
8
+ * Coverage: 1 advance-derived caps, 74 caps with 367 state leaves.
9
9
  */
10
10
  /** A bindable scalar in a capability's runtime state. */
11
11
  export interface CapStateLeaf {
@@ -59,6 +59,7 @@ import type { PtzAutotrackStatusSchema } from '../capabilities/ptz-autotrack.cap
59
59
  import type { recordingArchiveCapability } from '../capabilities/recording-archive.cap.js';
60
60
  import type { RecordingOnboardStatusSchema } from '../capabilities/recording-onboard.cap.js';
61
61
  import type { RecordingSignalStatusSchema } from '../capabilities/recording-signal.cap.js';
62
+ import type { RunningStateStatusSchema } from '../capabilities/running-state.cap.js';
62
63
  import type { SceneMonitorStatusSchema } from '../capabilities/scene-monitor.cap.js';
63
64
  import type { ScriptRunnerStatusSchema } from '../capabilities/script-runner.cap.js';
64
65
  import type { SmokeStatusSchema } from '../capabilities/smoke.cap.js';
@@ -139,6 +140,7 @@ export type CapStatusTypeMap = {
139
140
  readonly 'recording-archive': z.infer<(typeof recordingArchiveCapability)['status']['schema']>;
140
141
  readonly 'recording-onboard': z.infer<typeof RecordingOnboardStatusSchema>;
141
142
  readonly 'recording-signal': z.infer<typeof RecordingSignalStatusSchema>;
143
+ readonly 'running-state': z.infer<typeof RunningStateStatusSchema>;
142
144
  readonly 'scene-monitor': z.infer<typeof SceneMonitorStatusSchema>;
143
145
  readonly 'script-runner': z.infer<typeof ScriptRunnerStatusSchema>;
144
146
  readonly 'smoke': z.infer<typeof SmokeStatusSchema>;
@@ -161,4 +163,4 @@ export type CapNameWithStatus = keyof CapStatusTypeMap;
161
163
  * aggregator to enumerate caps whose `status` should be polled +
162
164
  * streamed via `subscribeDeviceStatusAggregate`.
163
165
  */
164
- export declare const CAP_NAMES_WITH_STATUS: readonly ["accessories", "air-quality-sensor", "alarm-panel", "ambient-light-sensor", "automation-control", "battery", "binary", "brightness", "broker", "camera-credentials", "carbon-monoxide", "climate-control", "color", "connectivity", "consumables", "contact", "control", "cover", "day-night", "device-adoption", "device-discovery", "device-export", "device-status", "dishwasher", "doorbell", "enum-sensor", "event-emitter", "fan-control", "feature-probe", "flood", "gas", "heating-valve", "humidifier", "humidity-sensor", "image", "image-settings", "intercom", "lawn-mower-control", "lock-control", "media-player", "motion", "motion-trigger", "motion-zones", "mqtt-broker", "native-object-detection", "navigation", "network-link", "notifier", "numeric-sensor", "osd", "pet-feeder", "power-meter", "presence", "pressure-sensor", "privacy-mask", "ptz", "ptz-autotrack", "recording-archive", "recording-onboard", "recording-signal", "scene-monitor", "script-runner", "smoke", "snapshot", "stream-params", "switch", "tamper", "temperature-sensor", "update", "vacuum-control", "valve", "vibration", "water-heater", "weather"];
166
+ export declare const CAP_NAMES_WITH_STATUS: readonly ["accessories", "air-quality-sensor", "alarm-panel", "ambient-light-sensor", "automation-control", "battery", "binary", "brightness", "broker", "camera-credentials", "carbon-monoxide", "climate-control", "color", "connectivity", "consumables", "contact", "control", "cover", "day-night", "device-adoption", "device-discovery", "device-export", "device-status", "dishwasher", "doorbell", "enum-sensor", "event-emitter", "fan-control", "feature-probe", "flood", "gas", "heating-valve", "humidifier", "humidity-sensor", "image", "image-settings", "intercom", "lawn-mower-control", "lock-control", "media-player", "motion", "motion-trigger", "motion-zones", "mqtt-broker", "native-object-detection", "navigation", "network-link", "notifier", "numeric-sensor", "osd", "pet-feeder", "power-meter", "presence", "pressure-sensor", "privacy-mask", "ptz", "ptz-autotrack", "recording-archive", "recording-onboard", "recording-signal", "running-state", "scene-monitor", "script-runner", "smoke", "snapshot", "stream-params", "switch", "tamper", "temperature-sensor", "update", "vacuum-control", "valve", "vibration", "water-heater", "weather"];
@@ -135,6 +135,7 @@ export { recordingExportCapability } from '../capabilities/recording-export.cap.
135
135
  export { recordingOnboardCapability } from '../capabilities/recording-onboard.cap.js';
136
136
  export { recordingSignalCapability } from '../capabilities/recording-signal.cap.js';
137
137
  export { recordsCapability } from '../capabilities/records.cap.js';
138
+ export { runningStateCapability } from '../capabilities/running-state.cap.js';
138
139
  export { sceneMonitorCapability } from '../capabilities/scene-monitor.cap.js';
139
140
  export { scriptRunnerCapability } from '../capabilities/script-runner.cap.js';
140
141
  export { serverManagementCapability } from '../capabilities/server-management.cap.js';
@@ -315,6 +316,7 @@ export declare const CAPABILITY_NAMES: {
315
316
  readonly recordingOnboard: 'recording-onboard';
316
317
  readonly recordingSignal: 'recording-signal';
317
318
  readonly records: 'records';
319
+ readonly runningState: 'running-state';
318
320
  readonly sceneMonitor: 'scene-monitor';
319
321
  readonly scriptRunner: 'script-runner';
320
322
  readonly serverManagement: 'server-management';
@@ -508,6 +510,7 @@ export interface CapabilityRouterMap<TRouter = unknown> {
508
510
  readonly recordingOnboard: TRouter;
509
511
  readonly recordingSignal: TRouter;
510
512
  readonly records: TRouter;
513
+ readonly runningState: TRouter;
511
514
  readonly sceneMonitor: TRouter;
512
515
  readonly scriptRunner: TRouter;
513
516
  readonly serverManagement: TRouter;
@@ -551,8 +554,8 @@ export interface CapabilityRouterMap<TRouter = unknown> {
551
554
  readonly zoneRules: TRouter;
552
555
  readonly zones: TRouter;
553
556
  }
554
- /** Capability names whose mode is `singleton` (144 caps). */
555
- export declare const SINGLETON_CAPABILITY_NAMES: readonly ['accessories', 'addon-pages', 'addon-settings', 'addon-widgets', 'addons', 'admin-ui', 'air-quality-sensor', 'alarm-panel', 'alerts', 'ambient-light-sensor', 'audio-analysis', 'audio-analyzer', 'audio-codec', 'audio-metrics', 'automation-control', 'backup', 'battery', 'binary', 'brightness', 'button', 'calendars', 'camera-credentials', 'camera-grid-layout', 'camera-pipeline-config', 'camera-streams', 'carbon-monoxide', 'climate-control', 'color', 'composer', 'connectivity', 'consumables', 'contact', 'control', 'core-blocks', 'cover', 'database-snapshot', 'day-night', 'decoder', 'detection-pipeline', 'device-admin-link', 'device-credentials', 'device-discovery', 'device-history', 'device-manager', 'device-ops', 'device-state', 'device-status', 'dishwasher', 'doorbell', 'enum-sensor', 'event-emitter', 'face-gallery', 'fan-control', 'feature-probe', 'filesystem-browse', 'flood', 'gas', 'heating-valve', 'humidifier', 'humidity-sensor', 'image', 'image-settings', 'integrations', 'intercom', 'keychain', 'keychain-admin', 'lawn-mower-control', 'llm-runtime', 'local-network', 'lock-control', 'media-player', 'metrics-provider', 'model-convert', 'model-distributor', 'motion', 'motion-detection', 'motion-trigger', 'motion-zones', 'native-object-detection', 'navigation', 'network-link', 'network-quality', 'node-certificates', 'nodes', 'notification-rules', 'notifier', 'numeric-sensor', 'oidc-connections', 'osd', 'osd-manager', 'pet-feeder', 'pipeline-analytics', 'pipeline-executor', 'pipeline-orchestrator', 'pipeline-runner', 'plate-gallery', 'platform-probe', 'power-meter', 'presence', 'pressure-sensor', 'privacy-mask', 'ptz', 'ptz-autotrack', 'reboot', 'record-entries', 'recording-archive', 'recording-export', 'recording-onboard', 'recording-signal', 'records', 'scene-monitor', 'script-runner', 'server-management', 'settings-store', 'smoke', 'snapshot', 'sso-bridge', 'storage', 'storage-admin', 'storage-migration', 'stream-broker', 'stream-catalog', 'stream-params', 'stream-signals', 'switch', 'system', 'tamper', 'temperature-sensor', 'terminal-session', 'toast', 'training', 'update', 'user-management', 'vacuum-control', 'valve', 'vector-store', 'vibration', 'viewer-ui', 'water-heater', 'weather', 'webrtc-session', 'zone-analytics', 'zone-rules', 'zones'];
557
+ /** Capability names whose mode is `singleton` (145 caps). */
558
+ export declare const SINGLETON_CAPABILITY_NAMES: readonly ['accessories', 'addon-pages', 'addon-settings', 'addon-widgets', 'addons', 'admin-ui', 'air-quality-sensor', 'alarm-panel', 'alerts', 'ambient-light-sensor', 'audio-analysis', 'audio-analyzer', 'audio-codec', 'audio-metrics', 'automation-control', 'backup', 'battery', 'binary', 'brightness', 'button', 'calendars', 'camera-credentials', 'camera-grid-layout', 'camera-pipeline-config', 'camera-streams', 'carbon-monoxide', 'climate-control', 'color', 'composer', 'connectivity', 'consumables', 'contact', 'control', 'core-blocks', 'cover', 'database-snapshot', 'day-night', 'decoder', 'detection-pipeline', 'device-admin-link', 'device-credentials', 'device-discovery', 'device-history', 'device-manager', 'device-ops', 'device-state', 'device-status', 'dishwasher', 'doorbell', 'enum-sensor', 'event-emitter', 'face-gallery', 'fan-control', 'feature-probe', 'filesystem-browse', 'flood', 'gas', 'heating-valve', 'humidifier', 'humidity-sensor', 'image', 'image-settings', 'integrations', 'intercom', 'keychain', 'keychain-admin', 'lawn-mower-control', 'llm-runtime', 'local-network', 'lock-control', 'media-player', 'metrics-provider', 'model-convert', 'model-distributor', 'motion', 'motion-detection', 'motion-trigger', 'motion-zones', 'native-object-detection', 'navigation', 'network-link', 'network-quality', 'node-certificates', 'nodes', 'notification-rules', 'notifier', 'numeric-sensor', 'oidc-connections', 'osd', 'osd-manager', 'pet-feeder', 'pipeline-analytics', 'pipeline-executor', 'pipeline-orchestrator', 'pipeline-runner', 'plate-gallery', 'platform-probe', 'power-meter', 'presence', 'pressure-sensor', 'privacy-mask', 'ptz', 'ptz-autotrack', 'reboot', 'record-entries', 'recording-archive', 'recording-export', 'recording-onboard', 'recording-signal', 'records', 'running-state', 'scene-monitor', 'script-runner', 'server-management', 'settings-store', 'smoke', 'snapshot', 'sso-bridge', 'storage', 'storage-admin', 'storage-migration', 'stream-broker', 'stream-catalog', 'stream-params', 'stream-signals', 'switch', 'system', 'tamper', 'temperature-sensor', 'terminal-session', 'toast', 'training', 'update', 'user-management', 'vacuum-control', 'valve', 'vector-store', 'vibration', 'viewer-ui', 'water-heater', 'weather', 'webrtc-session', 'zone-analytics', 'zone-rules', 'zones'];
556
559
  /** Union of singleton capability names (literal string union). */
557
560
  export type SingletonCapabilityName = typeof SINGLETON_CAPABILITY_NAMES[number];
558
561
  /** Capability names whose mode is `collection` (35 caps). */
@@ -52,6 +52,7 @@ import { privacyMaskCapability } from '../capabilities/privacy-mask.cap.js';
52
52
  import { ptzAutotrackCapability } from '../capabilities/ptz-autotrack.cap.js';
53
53
  import { recordingOnboardCapability } from '../capabilities/recording-onboard.cap.js';
54
54
  import { recordingSignalCapability } from '../capabilities/recording-signal.cap.js';
55
+ import { runningStateCapability } from '../capabilities/running-state.cap.js';
55
56
  import { sceneMonitorCapability } from '../capabilities/scene-monitor.cap.js';
56
57
  import { scriptRunnerCapability } from '../capabilities/script-runner.cap.js';
57
58
  import { smokeCapability } from '../capabilities/smoke.cap.js';
@@ -135,6 +136,7 @@ export interface DeviceLocalState {
135
136
  ptzAutotrack: InferRuntimeState<typeof ptzAutotrackCapability>;
136
137
  recordingOnboard: InferRuntimeState<typeof recordingOnboardCapability>;
137
138
  recordingSignal: InferRuntimeState<typeof recordingSignalCapability>;
139
+ runningState: InferRuntimeState<typeof runningStateCapability>;
138
140
  sceneMonitor: InferRuntimeState<typeof sceneMonitorCapability>;
139
141
  scriptRunner: InferRuntimeState<typeof scriptRunnerCapability>;
140
142
  smoke: InferRuntimeState<typeof smokeCapability>;
@@ -228,6 +230,7 @@ export interface CapNameToRuntimeStateMap {
228
230
  'ptz-autotrack': InferRuntimeState<typeof ptzAutotrackCapability>;
229
231
  'recording-onboard': InferRuntimeState<typeof recordingOnboardCapability>;
230
232
  'recording-signal': InferRuntimeState<typeof recordingSignalCapability>;
233
+ 'running-state': InferRuntimeState<typeof runningStateCapability>;
231
234
  'scene-monitor': InferRuntimeState<typeof sceneMonitorCapability>;
232
235
  'script-runner': InferRuntimeState<typeof scriptRunnerCapability>;
233
236
  'smoke': InferRuntimeState<typeof smokeCapability>;
@@ -71,6 +71,7 @@ import type { rebootCapability } from '../capabilities/reboot.cap.js';
71
71
  import type { recordingCapability } from '../capabilities/recording.cap.js';
72
72
  import type { recordingOnboardCapability } from '../capabilities/recording-onboard.cap.js';
73
73
  import type { recordingSignalCapability } from '../capabilities/recording-signal.cap.js';
74
+ import type { runningStateCapability } from '../capabilities/running-state.cap.js';
74
75
  import type { sceneMonitorCapability } from '../capabilities/scene-monitor.cap.js';
75
76
  import type { scriptRunnerCapability } from '../capabilities/script-runner.cap.js';
76
77
  import type { smokeCapability } from '../capabilities/smoke.cap.js';
@@ -169,6 +170,7 @@ export interface DeviceProxyState {
169
170
  readonly ptzAutotrack: SliceHandle<InferRuntimeState<typeof ptzAutotrackCapability>>;
170
171
  readonly recordingOnboard: SliceHandle<InferRuntimeState<typeof recordingOnboardCapability>>;
171
172
  readonly recordingSignal: SliceHandle<InferRuntimeState<typeof recordingSignalCapability>>;
173
+ readonly runningState: SliceHandle<InferRuntimeState<typeof runningStateCapability>>;
172
174
  readonly sceneMonitor: SliceHandle<InferRuntimeState<typeof sceneMonitorCapability>>;
173
175
  readonly scriptRunner: SliceHandle<InferRuntimeState<typeof scriptRunnerCapability>>;
174
176
  readonly smoke: SliceHandle<InferRuntimeState<typeof smokeCapability>>;
@@ -275,6 +277,7 @@ export interface DeviceProxy {
275
277
  readonly recording?: InferDeviceProxyCap<typeof recordingCapability>;
276
278
  readonly recordingOnboard?: InferDeviceProxyCap<typeof recordingOnboardCapability>;
277
279
  readonly recordingSignal?: InferDeviceProxyCap<typeof recordingSignalCapability>;
280
+ readonly runningState?: InferDeviceProxyCap<typeof runningStateCapability>;
278
281
  readonly sceneMonitor?: InferDeviceProxyCap<typeof sceneMonitorCapability>;
279
282
  readonly scriptRunner?: InferDeviceProxyCap<typeof scriptRunnerCapability>;
280
283
  readonly smoke?: InferDeviceProxyCap<typeof smokeCapability>;
@@ -5,7 +5,7 @@
5
5
  * can answer "may a rule actuate this?" without importing the schema barrel
6
6
  * (~144MB RSS per runner, D28).
7
7
  *
8
- * Coverage: 90 device-scoped capabilities.
8
+ * Coverage: 91 device-scoped capabilities.
9
9
  */
10
10
  export declare const DEVICE_SCOPED_CAPS: ReadonlySet<string>;
11
11
  /**
@@ -1,7 +1,7 @@
1
1
  import type { CapabilityHistoryField, CapabilityHistoryItems } from '../capabilities/capability-definition.js';
2
2
  /**
3
3
  * Cap history catalog, projected from every `*.cap.ts` `history` block.
4
- * 40 caps with series (73 series), 30 caps answered `'none'`.
4
+ * 41 caps with series (74 series), 30 caps answered `'none'`.
5
5
  * Field keys are `runtimeState` paths (`a.b` into fixed objects only).
6
6
  */
7
7
  export declare const HISTORY_CATALOG: Readonly<Record<string, Readonly<Record<string, CapabilityHistoryField>>>>;
@@ -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: 1378 method paths across 179 capabilities.
9
+ * Coverage: 1379 method paths across 180 capabilities.
10
10
  */
11
11
  import type { MethodRole } from '../auth/viewer-access.js';
12
12
  import type { CapabilityMethodAccess } from '../capabilities/capability-definition.js';
@@ -6,7 +6,7 @@
6
6
  * system-scope cap that takes a deviceId was previously never device-filtered
7
7
  * — see the generator header).
8
8
  *
9
- * Coverage: 545 methods carry a device reference, of which
9
+ * Coverage: 546 methods carry a device reference, of which
10
10
  * 174 are on SYSTEM-scope caps.
11
11
  *
12
12
  * Top-level fields, number arrays, and one-level arrays of objects carrying
@@ -11,7 +11,7 @@ export interface RuntimeStatePolicy {
11
11
  }
12
12
  /**
13
13
  * Per-cap runtime-state policy, projected from every `*.cap.ts` that declares
14
- * `runtimeState`. 71 caps: 37 `restored`, 34 `session`.
14
+ * `runtimeState`. 72 caps: 38 `restored`, 34 `session`.
15
15
  *
16
16
  * A cap absent from this map has no runtime-state slice at all. A cap PRESENT
17
17
  * with `durability: 'session'` has one and has decided not to keep it.
package/dist/index.d.ts CHANGED
@@ -164,6 +164,9 @@ export type { AutomationAction, AutomationCondition, AutomationConditionAll, Aut
164
164
  export { AutomationActionSchema, AutomationConditionOperatorSchema, AutomationConditionSchema, AutomationRecipeSchema, AutomationTriggerSchema, conditionDepth, countConditionLeaves, generateAutomationBlock, MAX_CONDITION_DEPTH, MAX_CONDITION_LEAVES, validateRecipeBounds, } from './automation/index.js';
165
165
  export * from './cap-call-context.js';
166
166
  export * from './capabilities/index.js';
167
+ export * from './running-state/assignment.js';
168
+ export * from './running-state/defaults.js';
169
+ export * from './running-state/from-operation.js';
167
170
  export * from './clips/clip-event-labels.js';
168
171
  export * from './device-extension/index.js';
169
172
  export * from './composition/index.js';
@@ -303,6 +306,7 @@ export { diffStepSettings, effectiveStepSettings, fieldsPinnedAtValueBelow, fiel
303
306
  export * from './pipeline/auto-tune/index.js';
304
307
  export * from './pipeline/load-balancing/index.js';
305
308
  export * from './pipeline/node-benchmark/index.js';
309
+ export * from './pipeline/second-pass/index.js';
306
310
  export { deriveRootFaceRefineRect, ROOT_FACE_REFINE_INPUT_PX, ROOT_FACE_REFINE_SCALE, } from './pipeline/root-face-crop.js';
307
311
  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';
308
312
  export { FACE_RESCORE_INTERVAL_FIELD, FACE_RESCORE_INTERVAL_KEY, FACE_RESCORE_INTERVAL_MIN_RUNNING, FACE_RESCORE_SECTION_ID, type FaceRescoreSettingsView, pickFaceRescoreIntervalMinutes, readFaceRescoreIntervalMinutes, } from './pipeline/face-rescore-schedule.js';