@camstack/types 1.2.432 → 1.2.434

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.
package/CHANGELOG.md CHANGED
@@ -7,11 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.2.434] - 2026-10-28
11
+
12
+ ### Added
13
+
14
+ - Automations can start on a parked object appearing or leaving, filtered by camera, class and zone, and check whether one is present
15
+
16
+ ## [1.2.433] - 2026-10-28
17
+
18
+ ### Changed
19
+
20
+ - Unknown event kinds, state words and class names read as words instead of raw ids
21
+ - Automations can start on, and be conditioned by, a parked object (appeared or departed, with class and zone filters)
22
+
10
23
  ## [1.2.432] - 2026-10-28
11
24
 
12
25
  ### Changed
13
26
 
14
27
  - The vendor login proxy is served on one shared vendor-login prefix that cannot shadow an addon's own routes
28
+ - Unknown event kinds and state words now read as a humanized label ("Delivery truck") instead of the raw id
15
29
 
16
30
  ## [1.2.431] - 2026-10-27
17
31
 
package/dist/addon.js CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_sleep = require("./sleep-5zRztaHa.js");
3
- const require_event_category = require("./event-category-BhzwWQCH.js");
2
+ const require_sleep = require("./sleep-CO61AfwW.js");
3
+ const require_event_category = require("./event-category-E17zaHjN.js");
4
4
  const require_err_msg = require("./err-msg-U7lLUMNz.js");
5
5
  //#region src/generated/cap-input-defaults.ts
6
6
  /**
package/dist/addon.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { $ as expandCapMethods, $n as REVALIDATE_AFTER_MS, $r as isSecretMarker, $t as RecordFieldPathSchema, A as HF_REPO, An as RecordUniqueViolationError, Ar as buildSecretRef, B as withoutCallerStamp, Bn as RECORD_CLASSES, C as addonSliceHandleApi, Cn as InvalidRecordError, Dn as RecordNotFoundError, En as RECORDS_ERROR_CODES, Fn as UnknownRecordKindError, Fr as parseSecretRef, G as adminUiCapability, Gn as RECORD_MAX_DATA_BYTES, Hn as RECORD_DEFAULT_MAX_DATA_BYTES, I as deviceOpsCapability, In as asRecordsError, Jn as RECORD_QUERY_MAX, Jt as defineEntryKind, Kn as RECORD_MAX_INDEXES, L as viewerUiCapability, Ln as recordsErrorFromMessage, M as CAP_ADVANCE_FIELDS, Mn as RevConflictError, Mr as globalSecretScope, Nn as TransactRefusedError, Nr as isSecretRef, On as RecordSecretUnavailableError, Or as SECRET_REF_SCHEME, P as CAP_STATE_LEAVES, Pn as UnindexedFilterError, Pr as normalizeSecretOwner, Qn as resolveSecretViewsIn, Qr as isSecretFieldView, Qt as EntryDescriptorSchema, R as DEVICE_CHILDREN_BATCH_MAX, Rn as RECORD_BATCH_MAX, Rr as createEvent, Sn as ForeignSecretMarkerError, Tn as PlaintextSecretError, U as describeCustomActions, Un as RECORD_DELETE_BATCH, Vn as RECORD_DATABASES, Wn as RECORD_ID_MAX_LENGTH, Xn as RECORD_SETTINGS_MAX_ROWS, Xr as classifySecretWrite, Xt as createRecordsAccess, Yn as RECORD_SECRET_COLLECTION_PREFIX, Yr as SECRET_CLEAR, Yt as entryBody, Zn as RECORD_SWEEP_INTERVAL_MS, Zr as isSecretClear, Zt as assertTransactScope, _ as readErrorI18n, _n as collectZodSecretPaths, an as assertValidDeclaration, ar as registerKnownSecret, b as isDeviceScopedCap, bn as DeclarationRefusedError, c as asString, cn as REMOVE_LEAF, cr as PEER_BYTES_CHUNK_BYTES, ct as readNodePin, d as parseJsonUnknown, dn as parseSecretPath, dr as PEER_BYTES_TICKET_TTL_MS, dt as ReadinessRegistry, ei as isSecretMarkerLike, en as RecordIndexSchema, er as createSecretsAccess, f as hfModelUrl, fn as recordArrayItemPath, ft as ReadinessTimeoutError, g as ErrorI18nPayloadSchema, gr as BaseAddon, hn as secretArrayPrefixes, hr as DisposerChain, ht as scopeKey, in as StoredRecordKindDeclarationSchema, ir as knownSecretCount, jn as RecordsError, jr as formatSecretScope, kn as RecordTooLargeError, kr as arrayItemFieldPath, ln as collectSecretLeaves, lr as PEER_BYTES_MAX_OUTSTANDING, mn as recordSecretRef, ni as toSecretFieldView, nn as RecordKindNameSchema, nr as clearKnownSecrets, o as asJsonObject, on as declarationsOf, or as scrubKnownSecrets, p as BOOT_RECOVERY_BACKOFF_MS, pn as recordSecretCollection, pr as DATAPLANE_SECRET_HEADER, qn as RECORD_MAX_INDEX_FIELDS, qt as makeInMemoryRecords, r as maskUrlCredentials, rn as RecordRetentionSchema, rr as forgetKnownSecret, sn as defineRecordKinds, sr as shortSecretRefHash, st as nodePin, t as sleep, ti as makeSecretMarker, tn as RecordKindDeclarationSchema, tr as MIN_SCRUBBED_LENGTH, un as mapSecretLeaves, ur as PEER_BYTES_STALL_MS, ut as MODEL_FORMATS, vn as isZodSecret, vr as normalizeAddonInitResult, w as createEventBusSliceSource, wn as NoCallerError, x as createDeviceProxy, xn as FilterRequiredError, y as DEVICE_SCOPED_CAPS, yn as BatchTooLargeError, z as CALLER_STAMPED_CAPABILITIES, zn as RECORD_BATCH_MAX_BYTES, zr as emitReadiness } from "./sleep-BHjNez61.mjs";
2
- import { t as EventCategory } from "./event-category-hdMR7CTW.mjs";
1
+ import { $ as expandCapMethods, $n as REVALIDATE_AFTER_MS, $r as isSecretMarker, $t as RecordFieldPathSchema, A as HF_REPO, An as RecordUniqueViolationError, Ar as buildSecretRef, B as withoutCallerStamp, Bn as RECORD_CLASSES, C as addonSliceHandleApi, Cn as InvalidRecordError, Dn as RecordNotFoundError, En as RECORDS_ERROR_CODES, Fn as UnknownRecordKindError, Fr as parseSecretRef, G as adminUiCapability, Gn as RECORD_MAX_DATA_BYTES, Hn as RECORD_DEFAULT_MAX_DATA_BYTES, I as deviceOpsCapability, In as asRecordsError, Jn as RECORD_QUERY_MAX, Jt as defineEntryKind, Kn as RECORD_MAX_INDEXES, L as viewerUiCapability, Ln as recordsErrorFromMessage, M as CAP_ADVANCE_FIELDS, Mn as RevConflictError, Mr as globalSecretScope, Nn as TransactRefusedError, Nr as isSecretRef, On as RecordSecretUnavailableError, Or as SECRET_REF_SCHEME, P as CAP_STATE_LEAVES, Pn as UnindexedFilterError, Pr as normalizeSecretOwner, Qn as resolveSecretViewsIn, Qr as isSecretFieldView, Qt as EntryDescriptorSchema, R as DEVICE_CHILDREN_BATCH_MAX, Rn as RECORD_BATCH_MAX, Rr as createEvent, Sn as ForeignSecretMarkerError, Tn as PlaintextSecretError, U as describeCustomActions, Un as RECORD_DELETE_BATCH, Vn as RECORD_DATABASES, Wn as RECORD_ID_MAX_LENGTH, Xn as RECORD_SETTINGS_MAX_ROWS, Xr as classifySecretWrite, Xt as createRecordsAccess, Yn as RECORD_SECRET_COLLECTION_PREFIX, Yr as SECRET_CLEAR, Yt as entryBody, Zn as RECORD_SWEEP_INTERVAL_MS, Zr as isSecretClear, Zt as assertTransactScope, _ as readErrorI18n, _n as collectZodSecretPaths, an as assertValidDeclaration, ar as registerKnownSecret, b as isDeviceScopedCap, bn as DeclarationRefusedError, c as asString, cn as REMOVE_LEAF, cr as PEER_BYTES_CHUNK_BYTES, ct as readNodePin, d as parseJsonUnknown, dn as parseSecretPath, dr as PEER_BYTES_TICKET_TTL_MS, dt as ReadinessRegistry, ei as isSecretMarkerLike, en as RecordIndexSchema, er as createSecretsAccess, f as hfModelUrl, fn as recordArrayItemPath, ft as ReadinessTimeoutError, g as ErrorI18nPayloadSchema, gr as BaseAddon, hn as secretArrayPrefixes, hr as DisposerChain, ht as scopeKey, in as StoredRecordKindDeclarationSchema, ir as knownSecretCount, jn as RecordsError, jr as formatSecretScope, kn as RecordTooLargeError, kr as arrayItemFieldPath, ln as collectSecretLeaves, lr as PEER_BYTES_MAX_OUTSTANDING, mn as recordSecretRef, ni as toSecretFieldView, nn as RecordKindNameSchema, nr as clearKnownSecrets, o as asJsonObject, on as declarationsOf, or as scrubKnownSecrets, p as BOOT_RECOVERY_BACKOFF_MS, pn as recordSecretCollection, pr as DATAPLANE_SECRET_HEADER, qn as RECORD_MAX_INDEX_FIELDS, qt as makeInMemoryRecords, r as maskUrlCredentials, rn as RecordRetentionSchema, rr as forgetKnownSecret, sn as defineRecordKinds, sr as shortSecretRefHash, st as nodePin, t as sleep, ti as makeSecretMarker, tn as RecordKindDeclarationSchema, tr as MIN_SCRUBBED_LENGTH, un as mapSecretLeaves, ur as PEER_BYTES_STALL_MS, ut as MODEL_FORMATS, vn as isZodSecret, vr as normalizeAddonInitResult, w as createEventBusSliceSource, wn as NoCallerError, x as createDeviceProxy, xn as FilterRequiredError, y as DEVICE_SCOPED_CAPS, yn as BatchTooLargeError, z as CALLER_STAMPED_CAPABILITIES, zn as RECORD_BATCH_MAX_BYTES, zr as emitReadiness } from "./sleep-DFaVPxfm.mjs";
2
+ import { t as EventCategory } from "./event-category-DmZDPDf_.mjs";
3
3
  import { a as DeviceType, t as errMsg } from "./err-msg-DIorGYeC.mjs";
4
4
  //#region src/generated/cap-input-defaults.ts
5
5
  /**
@@ -14,11 +14,13 @@ export type { ConditionEvaluation, ConditionReader, MirrorRefreshFetchers, Mirro
14
14
  export { collectMirrorSources, ConditionMirror, evaluateConditionTree, } from './condition-eval.js';
15
15
  export type { DetectionDecision, DetectionTrigger, DetectionVars, TrackLifecycleInput, } from './detection-trigger.js';
16
16
  export { DetectionTriggerFilter, detectionClassMatches, FIRED_MAX, FIRED_TTL_MS, } from './detection-trigger.js';
17
+ export type { StationaryChangedInput, StationaryDecision, StationaryTrigger, StationaryVars, } from './stationary-trigger.js';
18
+ export { evaluateStationaryTrigger } from './stationary-trigger.js';
17
19
  export type { CooldownInput, CooldownVerdict, RunGateAdmission } from './run-gate.js';
18
20
  export { RunGate } from './run-gate.js';
19
21
  export type { AutomationConditionTraceNode, AutomationRunOutcome, AutomationRunTrace, AutomationRunVerdict, AutomationStateDoc, AutomationStepTrace, AutomationTriggerTrace, TraceNodeOutcome, TraceValue, } from './trace.js';
20
22
  export { AutomationConditionTraceNodeSchema, EMPTY_AUTOMATION_STATE, mergeSkipTraces, AutomationRunOutcomeSchema, AutomationRunTraceSchema, AutomationRunVerdictSchema, AutomationStateDocSchema, AutomationStepTraceSchema, AutomationTriggerTraceSchema, appendTrace, buildTriggerTrace, isSkippedTrace, skipSignature, TraceNodeOutcomeSchema, TraceValueSchema, } from './trace.js';
21
- export type { ActionStep, AutomationAction, AutomationCondition, AutomationConditionAll, AutomationConditionAny, AutomationConditionExpression, AutomationConditionLeaf, AutomationConditionNot, AutomationConditionOperator, AutomationRecipe, AutomationRunMode, AutomationTrigger, } from './recipe.js';
23
+ export type { ActionStep, AutomationAction, AutomationCondition, AutomationConditionAll, AutomationConditionAny, AutomationConditionExpression, AutomationConditionLeaf, AutomationConditionNot, AutomationConditionOperator, AutomationConditionStationaryPresent, AutomationRecipe, AutomationRunMode, AutomationTrigger, } from './recipe.js';
22
24
  export { ActionStepSchema, AutomationActionSchema, AutomationCapStepSchema, AutomationWaitStepSchema, AutomationConditionOperatorSchema, AutomationConditionSchema, AutomationRecipeSchema, AutomationRunModeSchema, AutomationTriggerSchema, conditionDepth, countConditionLeaves, DEFAULT_TRACE_KEEP, MAX_TRACE_KEEP, MAX_CONDITION_DEPTH, MAX_CONDITION_LEAVES, validateRecipeBounds, } from './recipe.js';
23
25
  export * from './action.js';
24
26
  export * from './step-runner.js';
@@ -11,10 +11,10 @@
11
11
  *
12
12
  * Three vocabularies, each salvaged rather than invented:
13
13
  *
14
- * - **Triggers** — the only genuinely new surface. Six members, none of which
14
+ * - **Triggers** — the only genuinely new surface. Seven members, none of which
15
15
  * touches notification delivery. The NC keeps its four *pipeline* triggers;
16
16
  * these are device/time triggers and the two sets do not overlap.
17
- * - **Conditions** — `ALL`/`ANY`/`NOT` over two leaf kinds, bounded. The
17
+ * - **Conditions** — `ALL`/`ANY`/`NOT` over three leaf kinds, bounded. The
18
18
  * expression leaf is the bounded engine at `../expression/`, which is where
19
19
  * arithmetic between two device fields lives and the only place it lives.
20
20
  * - **Actions** — `NcRuleActionSchema`'s two steps, plus the `{kind:'code'}`
@@ -66,6 +66,18 @@ export interface AutomationConditionExpression {
66
66
  readonly expr: string;
67
67
  readonly bindings: Readonly<Record<string, ExpressionBindingSource>>;
68
68
  }
69
+ /**
70
+ * True when the camera currently has a PARKED object (stationary registry)
71
+ * matching `classes` (macro classes match like the detection trigger) in at
72
+ * least one of `zones`. Reads the zone-analytics snapshot through the same
73
+ * mirror as every other leaf, so a dropped event never decides it (D49).
74
+ */
75
+ export interface AutomationConditionStationaryPresent {
76
+ readonly kind: 'stationary-present';
77
+ readonly deviceId: number;
78
+ readonly classes?: readonly string[];
79
+ readonly zones?: readonly string[];
80
+ }
69
81
  export interface AutomationConditionAll {
70
82
  readonly kind: 'all';
71
83
  readonly children: readonly AutomationCondition[];
@@ -78,7 +90,7 @@ export interface AutomationConditionNot {
78
90
  readonly kind: 'not';
79
91
  readonly child: AutomationCondition;
80
92
  }
81
- export type AutomationCondition = AutomationConditionAll | AutomationConditionAny | AutomationConditionNot | AutomationConditionLeaf | AutomationConditionExpression;
93
+ export type AutomationCondition = AutomationConditionAll | AutomationConditionAny | AutomationConditionNot | AutomationConditionLeaf | AutomationConditionExpression | AutomationConditionStationaryPresent;
82
94
  export declare const AutomationConditionSchema: z.ZodType<AutomationCondition>;
83
95
  /**
84
96
  * What starts a run.
@@ -114,6 +126,15 @@ export declare const AutomationTriggerSchema: z.ZodDiscriminatedUnion<[z.ZodObje
114
126
  deviceIds: z.ZodArray<z.ZodNumber>;
115
127
  zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
116
128
  minScore: z.ZodOptional<z.ZodNumber>;
129
+ }, z.core.$strip>, z.ZodObject<{
130
+ kind: z.ZodLiteral<"stationary">;
131
+ deviceIds: z.ZodArray<z.ZodNumber>;
132
+ classes: z.ZodOptional<z.ZodArray<z.ZodString>>;
133
+ zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
134
+ phase: z.ZodEnum<{
135
+ appeared: "appeared";
136
+ departed: "departed";
137
+ }>;
117
138
  }, z.core.$strip>, z.ZodObject<{
118
139
  kind: z.ZodLiteral<"interval">;
119
140
  minutes: z.ZodNumber;
@@ -243,6 +264,15 @@ export declare const AutomationRecipeSchema: z.ZodObject<{
243
264
  deviceIds: z.ZodArray<z.ZodNumber>;
244
265
  zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
245
266
  minScore: z.ZodOptional<z.ZodNumber>;
267
+ }, z.core.$strip>, z.ZodObject<{
268
+ kind: z.ZodLiteral<"stationary">;
269
+ deviceIds: z.ZodArray<z.ZodNumber>;
270
+ classes: z.ZodOptional<z.ZodArray<z.ZodString>>;
271
+ zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
272
+ phase: z.ZodEnum<{
273
+ appeared: "appeared";
274
+ departed: "departed";
275
+ }>;
246
276
  }, z.core.$strip>, z.ZodObject<{
247
277
  kind: z.ZodLiteral<"interval">;
248
278
  minutes: z.ZodNumber;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * The `stationary` trigger's per-event decision: does this parked-object change
3
+ * start a run, and if not, WHY not.
4
+ *
5
+ * Source: `EventCategory.PipelineAnalyticsStationaryChanged` — payload
6
+ * {@link PipelineAnalyticsStationaryChangedPayload} (`deviceId`, `entryId`,
7
+ * `className`, `phase` appeared|departed, `zones`). The device is in the DATA.
8
+ *
9
+ * Stateless: the registry emits one event per transition, so there is no
10
+ * once-per-subject set to keep (unlike `detection`, whose track emits many
11
+ * updates). A change of the OTHER phase is not this trigger's business and is
12
+ * ignored without a trace. Events are telemetry (D8): a dropped one delays or
13
+ * misses a fire, and nothing durable depends on it.
14
+ */
15
+ import type { PipelineAnalyticsStationaryChangedPayload } from '../interfaces/event-bus.js';
16
+ import type { AutomationTrigger } from './recipe.js';
17
+ export type StationaryTrigger = Extract<AutomationTrigger, {
18
+ kind: 'stationary';
19
+ }>;
20
+ /** The fields of a stationary-changed event the trigger reads (all `unknown`: off the bus). */
21
+ export interface StationaryChangedInput {
22
+ readonly deviceId?: unknown;
23
+ readonly entryId?: unknown;
24
+ readonly className?: unknown;
25
+ readonly phase?: unknown;
26
+ readonly zones?: unknown;
27
+ }
28
+ /** What a stationary run exposes to conditions and actions. */
29
+ export interface StationaryVars {
30
+ readonly deviceId: number;
31
+ readonly className: string;
32
+ readonly zones: readonly string[];
33
+ readonly phase: PipelineAnalyticsStationaryChangedPayload['phase'];
34
+ readonly entryId: string;
35
+ }
36
+ export type StationaryDecision = {
37
+ readonly kind: 'ignore';
38
+ readonly why: string;
39
+ } | {
40
+ readonly kind: 'reject';
41
+ readonly reason: string;
42
+ readonly vars: StationaryVars;
43
+ } | {
44
+ readonly kind: 'fire';
45
+ readonly reason: string;
46
+ readonly vars: StationaryVars;
47
+ };
48
+ export declare function evaluateStationaryTrigger(trigger: StationaryTrigger, event: StationaryChangedInput): StationaryDecision;
@@ -52,6 +52,7 @@ export declare const AutomationConditionTraceNodeSchema: z.ZodObject<{
52
52
  condition: "condition";
53
53
  expression: "expression";
54
54
  not: "not";
55
+ "stationary-present": "stationary-present";
55
56
  }>;
56
57
  outcome: z.ZodEnum<{
57
58
  fail: "fail";
@@ -131,6 +132,7 @@ export declare const AutomationRunTraceSchema: z.ZodObject<{
131
132
  condition: "condition";
132
133
  expression: "expression";
133
134
  not: "not";
135
+ "stationary-present": "stationary-present";
134
136
  }>;
135
137
  outcome: z.ZodEnum<{
136
138
  fail: "fail";
@@ -226,6 +228,7 @@ export declare const AutomationStateDocSchema: z.ZodObject<{
226
228
  condition: "condition";
227
229
  expression: "expression";
228
230
  not: "not";
231
+ "stationary-present": "stationary-present";
229
232
  }>;
230
233
  outcome: z.ZodEnum<{
231
234
  fail: "fail";
@@ -319,7 +322,7 @@ export declare function mergeSkipTraces(prev: AutomationRunTrace, next: Automati
319
322
  export declare function appendTrace(ring: readonly AutomationRunTrace[], trace: AutomationRunTrace, keep: number): AutomationRunTrace[];
320
323
  /**
321
324
  * The trigger stage of a trace from the bag a trigger handed to `run()`:
322
- * primitives only (a device-state `to` that is an object is left out), minus the
325
+ * primitives and short lists of them (a device-state `to` that is an object is left out), minus the
323
326
  * bookkeeping keys `kind` and `at`.
324
327
  */
325
328
  export declare function buildTriggerTrace(trigger: Readonly<Record<string, unknown>>, outcome: 'pass' | 'fail', reason: string): AutomationTriggerTrace;
@@ -157,6 +157,7 @@ export declare const actionsCapability: {
157
157
  condition: "condition";
158
158
  expression: "expression";
159
159
  not: "not";
160
+ "stationary-present": "stationary-present";
160
161
  }>;
161
162
  outcome: z.ZodEnum<{
162
163
  fail: "fail";
@@ -163,6 +163,15 @@ export declare const CoreBlockSourceSchema: z.ZodDiscriminatedUnion<[z.ZodObject
163
163
  deviceIds: z.ZodArray<z.ZodNumber>;
164
164
  zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
165
165
  minScore: z.ZodOptional<z.ZodNumber>;
166
+ }, z.core.$strip>, z.ZodObject<{
167
+ kind: z.ZodLiteral<"stationary">;
168
+ deviceIds: z.ZodArray<z.ZodNumber>;
169
+ classes: z.ZodOptional<z.ZodArray<z.ZodString>>;
170
+ zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
171
+ phase: z.ZodEnum<{
172
+ appeared: "appeared";
173
+ departed: "departed";
174
+ }>;
166
175
  }, z.core.$strip>, z.ZodObject<{
167
176
  kind: z.ZodLiteral<"interval">;
168
177
  minutes: z.ZodNumber;
@@ -675,6 +684,15 @@ export declare const CoreBlockSchema: z.ZodObject<{
675
684
  deviceIds: z.ZodArray<z.ZodNumber>;
676
685
  zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
677
686
  minScore: z.ZodOptional<z.ZodNumber>;
687
+ }, z.core.$strip>, z.ZodObject<{
688
+ kind: z.ZodLiteral<"stationary">;
689
+ deviceIds: z.ZodArray<z.ZodNumber>;
690
+ classes: z.ZodOptional<z.ZodArray<z.ZodString>>;
691
+ zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
692
+ phase: z.ZodEnum<{
693
+ appeared: "appeared";
694
+ departed: "departed";
695
+ }>;
678
696
  }, z.core.$strip>, z.ZodObject<{
679
697
  kind: z.ZodLiteral<"interval">;
680
698
  minutes: z.ZodNumber;
@@ -1013,6 +1031,15 @@ export declare const CompositionViewSchema: z.ZodObject<{
1013
1031
  deviceIds: z.ZodArray<z.ZodNumber>;
1014
1032
  zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
1015
1033
  minScore: z.ZodOptional<z.ZodNumber>;
1034
+ }, z.core.$strip>, z.ZodObject<{
1035
+ kind: z.ZodLiteral<"stationary">;
1036
+ deviceIds: z.ZodArray<z.ZodNumber>;
1037
+ classes: z.ZodOptional<z.ZodArray<z.ZodString>>;
1038
+ zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
1039
+ phase: z.ZodEnum<{
1040
+ appeared: "appeared";
1041
+ departed: "departed";
1042
+ }>;
1016
1043
  }, z.core.$strip>, z.ZodObject<{
1017
1044
  kind: z.ZodLiteral<"interval">;
1018
1045
  minutes: z.ZodNumber;
@@ -1349,6 +1376,15 @@ export declare const CompositionListReadSchema: z.ZodDiscriminatedUnion<[z.ZodOb
1349
1376
  deviceIds: z.ZodArray<z.ZodNumber>;
1350
1377
  zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
1351
1378
  minScore: z.ZodOptional<z.ZodNumber>;
1379
+ }, z.core.$strip>, z.ZodObject<{
1380
+ kind: z.ZodLiteral<"stationary">;
1381
+ deviceIds: z.ZodArray<z.ZodNumber>;
1382
+ classes: z.ZodOptional<z.ZodArray<z.ZodString>>;
1383
+ zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
1384
+ phase: z.ZodEnum<{
1385
+ appeared: "appeared";
1386
+ departed: "departed";
1387
+ }>;
1352
1388
  }, z.core.$strip>, z.ZodObject<{
1353
1389
  kind: z.ZodLiteral<"interval">;
1354
1390
  minutes: z.ZodNumber;
@@ -1689,6 +1725,15 @@ export declare const CompositionGetReadSchema: z.ZodDiscriminatedUnion<[z.ZodObj
1689
1725
  deviceIds: z.ZodArray<z.ZodNumber>;
1690
1726
  zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
1691
1727
  minScore: z.ZodOptional<z.ZodNumber>;
1728
+ }, z.core.$strip>, z.ZodObject<{
1729
+ kind: z.ZodLiteral<"stationary">;
1730
+ deviceIds: z.ZodArray<z.ZodNumber>;
1731
+ classes: z.ZodOptional<z.ZodArray<z.ZodString>>;
1732
+ zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
1733
+ phase: z.ZodEnum<{
1734
+ appeared: "appeared";
1735
+ departed: "departed";
1736
+ }>;
1692
1737
  }, z.core.$strip>, z.ZodObject<{
1693
1738
  kind: z.ZodLiteral<"interval">;
1694
1739
  minutes: z.ZodNumber;
@@ -2030,6 +2075,15 @@ export declare const CompositionCustomizationReadSchema: z.ZodDiscriminatedUnion
2030
2075
  deviceIds: z.ZodArray<z.ZodNumber>;
2031
2076
  zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
2032
2077
  minScore: z.ZodOptional<z.ZodNumber>;
2078
+ }, z.core.$strip>, z.ZodObject<{
2079
+ kind: z.ZodLiteral<"stationary">;
2080
+ deviceIds: z.ZodArray<z.ZodNumber>;
2081
+ classes: z.ZodOptional<z.ZodArray<z.ZodString>>;
2082
+ zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
2083
+ phase: z.ZodEnum<{
2084
+ appeared: "appeared";
2085
+ departed: "departed";
2086
+ }>;
2033
2087
  }, z.core.$strip>, z.ZodObject<{
2034
2088
  kind: z.ZodLiteral<"interval">;
2035
2089
  minutes: z.ZodNumber;
@@ -2391,6 +2445,15 @@ export declare const coreBlocksCapability: {
2391
2445
  deviceIds: z.ZodArray<z.ZodNumber>;
2392
2446
  zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
2393
2447
  minScore: z.ZodOptional<z.ZodNumber>;
2448
+ }, z.core.$strip>, z.ZodObject<{
2449
+ kind: z.ZodLiteral<"stationary">;
2450
+ deviceIds: z.ZodArray<z.ZodNumber>;
2451
+ classes: z.ZodOptional<z.ZodArray<z.ZodString>>;
2452
+ zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
2453
+ phase: z.ZodEnum<{
2454
+ appeared: "appeared";
2455
+ departed: "departed";
2456
+ }>;
2394
2457
  }, z.core.$strip>, z.ZodObject<{
2395
2458
  kind: z.ZodLiteral<"interval">;
2396
2459
  minutes: z.ZodNumber;
@@ -2691,6 +2754,15 @@ export declare const coreBlocksCapability: {
2691
2754
  deviceIds: z.ZodArray<z.ZodNumber>;
2692
2755
  zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
2693
2756
  minScore: z.ZodOptional<z.ZodNumber>;
2757
+ }, z.core.$strip>, z.ZodObject<{
2758
+ kind: z.ZodLiteral<"stationary">;
2759
+ deviceIds: z.ZodArray<z.ZodNumber>;
2760
+ classes: z.ZodOptional<z.ZodArray<z.ZodString>>;
2761
+ zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
2762
+ phase: z.ZodEnum<{
2763
+ appeared: "appeared";
2764
+ departed: "departed";
2765
+ }>;
2694
2766
  }, z.core.$strip>, z.ZodObject<{
2695
2767
  kind: z.ZodLiteral<"interval">;
2696
2768
  minutes: z.ZodNumber;
@@ -3005,6 +3077,15 @@ export declare const coreBlocksCapability: {
3005
3077
  deviceIds: z.ZodArray<z.ZodNumber>;
3006
3078
  zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
3007
3079
  minScore: z.ZodOptional<z.ZodNumber>;
3080
+ }, z.core.$strip>, z.ZodObject<{
3081
+ kind: z.ZodLiteral<"stationary">;
3082
+ deviceIds: z.ZodArray<z.ZodNumber>;
3083
+ classes: z.ZodOptional<z.ZodArray<z.ZodString>>;
3084
+ zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
3085
+ phase: z.ZodEnum<{
3086
+ appeared: "appeared";
3087
+ departed: "departed";
3088
+ }>;
3008
3089
  }, z.core.$strip>, z.ZodObject<{
3009
3090
  kind: z.ZodLiteral<"interval">;
3010
3091
  minutes: z.ZodNumber;
@@ -3317,6 +3398,15 @@ export declare const coreBlocksCapability: {
3317
3398
  deviceIds: z.ZodArray<z.ZodNumber>;
3318
3399
  zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
3319
3400
  minScore: z.ZodOptional<z.ZodNumber>;
3401
+ }, z.core.$strip>, z.ZodObject<{
3402
+ kind: z.ZodLiteral<"stationary">;
3403
+ deviceIds: z.ZodArray<z.ZodNumber>;
3404
+ classes: z.ZodOptional<z.ZodArray<z.ZodString>>;
3405
+ zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
3406
+ phase: z.ZodEnum<{
3407
+ appeared: "appeared";
3408
+ departed: "departed";
3409
+ }>;
3320
3410
  }, z.core.$strip>, z.ZodObject<{
3321
3411
  kind: z.ZodLiteral<"interval">;
3322
3412
  minutes: z.ZodNumber;
@@ -3625,6 +3715,15 @@ export declare const coreBlocksCapability: {
3625
3715
  deviceIds: z.ZodArray<z.ZodNumber>;
3626
3716
  zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
3627
3717
  minScore: z.ZodOptional<z.ZodNumber>;
3718
+ }, z.core.$strip>, z.ZodObject<{
3719
+ kind: z.ZodLiteral<"stationary">;
3720
+ deviceIds: z.ZodArray<z.ZodNumber>;
3721
+ classes: z.ZodOptional<z.ZodArray<z.ZodString>>;
3722
+ zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
3723
+ phase: z.ZodEnum<{
3724
+ appeared: "appeared";
3725
+ departed: "departed";
3726
+ }>;
3628
3727
  }, z.core.$strip>, z.ZodObject<{
3629
3728
  kind: z.ZodLiteral<"interval">;
3630
3729
  minutes: z.ZodNumber;
@@ -3938,6 +4037,15 @@ export declare const coreBlocksCapability: {
3938
4037
  deviceIds: z.ZodArray<z.ZodNumber>;
3939
4038
  zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
3940
4039
  minScore: z.ZodOptional<z.ZodNumber>;
4040
+ }, z.core.$strip>, z.ZodObject<{
4041
+ kind: z.ZodLiteral<"stationary">;
4042
+ deviceIds: z.ZodArray<z.ZodNumber>;
4043
+ classes: z.ZodOptional<z.ZodArray<z.ZodString>>;
4044
+ zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
4045
+ phase: z.ZodEnum<{
4046
+ appeared: "appeared";
4047
+ departed: "departed";
4048
+ }>;
3941
4049
  }, z.core.$strip>, z.ZodObject<{
3942
4050
  kind: z.ZodLiteral<"interval">;
3943
4051
  minutes: z.ZodNumber;
@@ -4546,6 +4654,15 @@ export declare const coreBlocksCapability: {
4546
4654
  deviceIds: z.ZodArray<z.ZodNumber>;
4547
4655
  zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
4548
4656
  minScore: z.ZodOptional<z.ZodNumber>;
4657
+ }, z.core.$strip>, z.ZodObject<{
4658
+ kind: z.ZodLiteral<"stationary">;
4659
+ deviceIds: z.ZodArray<z.ZodNumber>;
4660
+ classes: z.ZodOptional<z.ZodArray<z.ZodString>>;
4661
+ zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
4662
+ phase: z.ZodEnum<{
4663
+ appeared: "appeared";
4664
+ departed: "departed";
4665
+ }>;
4549
4666
  }, z.core.$strip>, z.ZodObject<{
4550
4667
  kind: z.ZodLiteral<"interval">;
4551
4668
  minutes: z.ZodNumber;
@@ -5058,6 +5175,15 @@ export declare const coreBlocksCapability: {
5058
5175
  deviceIds: z.ZodArray<z.ZodNumber>;
5059
5176
  zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
5060
5177
  minScore: z.ZodOptional<z.ZodNumber>;
5178
+ }, z.core.$strip>, z.ZodObject<{
5179
+ kind: z.ZodLiteral<"stationary">;
5180
+ deviceIds: z.ZodArray<z.ZodNumber>;
5181
+ classes: z.ZodOptional<z.ZodArray<z.ZodString>>;
5182
+ zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
5183
+ phase: z.ZodEnum<{
5184
+ appeared: "appeared";
5185
+ departed: "departed";
5186
+ }>;
5061
5187
  }, z.core.$strip>, z.ZodObject<{
5062
5188
  kind: z.ZodLiteral<"interval">;
5063
5189
  minutes: z.ZodNumber;
@@ -5363,6 +5489,15 @@ export declare const coreBlocksCapability: {
5363
5489
  deviceIds: z.ZodArray<z.ZodNumber>;
5364
5490
  zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
5365
5491
  minScore: z.ZodOptional<z.ZodNumber>;
5492
+ }, z.core.$strip>, z.ZodObject<{
5493
+ kind: z.ZodLiteral<"stationary">;
5494
+ deviceIds: z.ZodArray<z.ZodNumber>;
5495
+ classes: z.ZodOptional<z.ZodArray<z.ZodString>>;
5496
+ zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
5497
+ phase: z.ZodEnum<{
5498
+ appeared: "appeared";
5499
+ departed: "departed";
5500
+ }>;
5366
5501
  }, z.core.$strip>, z.ZodObject<{
5367
5502
  kind: z.ZodLiteral<"interval">;
5368
5503
  minutes: z.ZodNumber;
@@ -5702,6 +5837,15 @@ export declare const coreBlocksCapability: {
5702
5837
  deviceIds: z.ZodArray<z.ZodNumber>;
5703
5838
  zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
5704
5839
  minScore: z.ZodOptional<z.ZodNumber>;
5840
+ }, z.core.$strip>, z.ZodObject<{
5841
+ kind: z.ZodLiteral<"stationary">;
5842
+ deviceIds: z.ZodArray<z.ZodNumber>;
5843
+ classes: z.ZodOptional<z.ZodArray<z.ZodString>>;
5844
+ zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
5845
+ phase: z.ZodEnum<{
5846
+ appeared: "appeared";
5847
+ departed: "departed";
5848
+ }>;
5705
5849
  }, z.core.$strip>, z.ZodObject<{
5706
5850
  kind: z.ZodLiteral<"interval">;
5707
5851
  minutes: z.ZodNumber;
@@ -6048,6 +6192,15 @@ export declare const coreBlocksCapability: {
6048
6192
  deviceIds: z.ZodArray<z.ZodNumber>;
6049
6193
  zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
6050
6194
  minScore: z.ZodOptional<z.ZodNumber>;
6195
+ }, z.core.$strip>, z.ZodObject<{
6196
+ kind: z.ZodLiteral<"stationary">;
6197
+ deviceIds: z.ZodArray<z.ZodNumber>;
6198
+ classes: z.ZodOptional<z.ZodArray<z.ZodString>>;
6199
+ zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
6200
+ phase: z.ZodEnum<{
6201
+ appeared: "appeared";
6202
+ departed: "departed";
6203
+ }>;
6051
6204
  }, z.core.$strip>, z.ZodObject<{
6052
6205
  kind: z.ZodLiteral<"interval">;
6053
6206
  minutes: z.ZodNumber;
@@ -6768,6 +6921,7 @@ export declare const coreBlocksCapability: {
6768
6921
  condition: "condition";
6769
6922
  expression: "expression";
6770
6923
  not: "not";
6924
+ "stationary-present": "stationary-present";
6771
6925
  }>;
6772
6926
  outcome: z.ZodEnum<{
6773
6927
  fail: "fail";
@@ -6864,6 +7018,7 @@ export declare const coreBlocksCapability: {
6864
7018
  condition: "condition";
6865
7019
  expression: "expression";
6866
7020
  not: "not";
7021
+ "stationary-present": "stationary-present";
6867
7022
  }>;
6868
7023
  outcome: z.ZodEnum<{
6869
7024
  fail: "fail";
@@ -6956,6 +7111,7 @@ export declare const coreBlocksCapability: {
6956
7111
  condition: "condition";
6957
7112
  expression: "expression";
6958
7113
  not: "not";
7114
+ "stationary-present": "stationary-present";
6959
7115
  }>;
6960
7116
  outcome: z.ZodEnum<{
6961
7117
  fail: "fail";
package/dist/client.js CHANGED
@@ -32032,7 +32032,41 @@ function packagePickerItems(packages) {
32032
32032
  return [...pinned, ...addons];
32033
32033
  }
32034
32034
  //#endregion
32035
+ //#region src/i18n/humanize-id.ts
32036
+ /**
32037
+ * Make a raw wire id readable when no dictionary knows it: `delivery_truck`
32038
+ * becomes "Delivery truck", `open-door` becomes "Open door". It invents no
32039
+ * translation — the words stay the id's own, only separators and the first
32040
+ * letter change. An empty id stays empty.
32041
+ */
32042
+ function humanizeId(id) {
32043
+ const spaced = id.replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim();
32044
+ return spaced.charAt(0).toUpperCase() + spaced.slice(1);
32045
+ }
32046
+ //#endregion
32035
32047
  //#region src/i18n/state-labels.ts
32048
+ /**
32049
+ * ONE dictionary of human labels for the state words the rule editors show
32050
+ * (R7, D690).
32051
+ *
32052
+ * A device-state gate offers the words the engine compares against —
32053
+ * `armed_away`, `not_home`, `unlocking` — and both rule editors printed them
32054
+ * verbatim. The words are the WIRE vocabulary and must stay what they are (a
32055
+ * rule stores them); what the operator reads is a label, and two editors that
32056
+ * each translate on their own are two editors that disagree. Both the admin UI
32057
+ * and the viewer resolve through {@link stateLabel}.
32058
+ *
32059
+ * Keys are the raw values themselves, flat: the vocabularies are disjoint where
32060
+ * they differ and agree where they overlap (`open` is the same word on a cover
32061
+ * and on a contact). An OPEN vocabulary (a presence zone the operator named,
32062
+ * a cover state a new integration invents) falls back to the raw word — never
32063
+ * an exception, never an empty chip.
32064
+ *
32065
+ * Covered, and held to their sources by the spec: the alarm panel's states,
32066
+ * the cover's, the lock's, the boolean readers' words
32067
+ * (`DEVICE_STATE_READERS`), presence's canonical `home`/`not_home`, and the
32068
+ * scene gate's verdicts and read modes.
32069
+ */
32036
32070
  /** Every key the dictionary answers for, in a stable order. */
32037
32071
  var STATE_LABEL_KEYS = [
32038
32072
  "disarmed",
@@ -32193,7 +32227,7 @@ function isStateLabelKey(key) {
32193
32227
  * dictionary does not know it. Never throws.
32194
32228
  */
32195
32229
  function stateLabel(key, locale) {
32196
- return isStateLabelKey(key) ? STATE_LABELS[key][locale] : key;
32230
+ return isStateLabelKey(key) ? STATE_LABELS[key][locale] : humanizeId(key);
32197
32231
  }
32198
32232
  //#endregion
32199
32233
  //#region src/notification/timelapse-rule.ts
package/dist/client.mjs CHANGED
@@ -32031,7 +32031,41 @@ function packagePickerItems(packages) {
32031
32031
  return [...pinned, ...addons];
32032
32032
  }
32033
32033
  //#endregion
32034
+ //#region src/i18n/humanize-id.ts
32035
+ /**
32036
+ * Make a raw wire id readable when no dictionary knows it: `delivery_truck`
32037
+ * becomes "Delivery truck", `open-door` becomes "Open door". It invents no
32038
+ * translation — the words stay the id's own, only separators and the first
32039
+ * letter change. An empty id stays empty.
32040
+ */
32041
+ function humanizeId(id) {
32042
+ const spaced = id.replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim();
32043
+ return spaced.charAt(0).toUpperCase() + spaced.slice(1);
32044
+ }
32045
+ //#endregion
32034
32046
  //#region src/i18n/state-labels.ts
32047
+ /**
32048
+ * ONE dictionary of human labels for the state words the rule editors show
32049
+ * (R7, D690).
32050
+ *
32051
+ * A device-state gate offers the words the engine compares against —
32052
+ * `armed_away`, `not_home`, `unlocking` — and both rule editors printed them
32053
+ * verbatim. The words are the WIRE vocabulary and must stay what they are (a
32054
+ * rule stores them); what the operator reads is a label, and two editors that
32055
+ * each translate on their own are two editors that disagree. Both the admin UI
32056
+ * and the viewer resolve through {@link stateLabel}.
32057
+ *
32058
+ * Keys are the raw values themselves, flat: the vocabularies are disjoint where
32059
+ * they differ and agree where they overlap (`open` is the same word on a cover
32060
+ * and on a contact). An OPEN vocabulary (a presence zone the operator named,
32061
+ * a cover state a new integration invents) falls back to the raw word — never
32062
+ * an exception, never an empty chip.
32063
+ *
32064
+ * Covered, and held to their sources by the spec: the alarm panel's states,
32065
+ * the cover's, the lock's, the boolean readers' words
32066
+ * (`DEVICE_STATE_READERS`), presence's canonical `home`/`not_home`, and the
32067
+ * scene gate's verdicts and read modes.
32068
+ */
32035
32069
  /** Every key the dictionary answers for, in a stable order. */
32036
32070
  var STATE_LABEL_KEYS = [
32037
32071
  "disarmed",
@@ -32192,7 +32226,7 @@ function isStateLabelKey(key) {
32192
32226
  * dictionary does not know it. Never throws.
32193
32227
  */
32194
32228
  function stateLabel(key, locale) {
32195
- return isStateLabelKey(key) ? STATE_LABELS[key][locale] : key;
32229
+ return isStateLabelKey(key) ? STATE_LABELS[key][locale] : humanizeId(key);
32196
32230
  }
32197
32231
  //#endregion
32198
32232
  //#region src/notification/timelapse-rule.ts
@@ -624,7 +624,7 @@ export declare enum EventCategory {
624
624
  * (a track was promoted to a stationary-registry entry) or departs (the
625
625
  * object moved / was removed). Telemetry (D8): lossy, drives a UI refresh of
626
626
  * the dedicated "Stationary" section — never the live event feed. Payload:
627
- * `{ deviceId, entryId, className, phase:'appeared'|'departed', timestamp }`.
627
+ * `{ deviceId, entryId, className, phase:'appeared'|'departed', timestamp, observedAt, zones }`.
628
628
  */
629
629
  PipelineAnalyticsStationaryChanged = "pipeline-analytics.stationary-changed",
630
630
  /**
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-BhzwWQCH.js");
2
+ const require_event_category = require("./event-category-E17zaHjN.js");
3
3
  //#region src/enums/event-source-type.ts
4
4
  var EventSourceType = /* @__PURE__ */ function(EventSourceType) {
5
5
  EventSourceType["Addon"] = "addon";