@camstack/types 1.2.451 → 1.2.453

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 (47) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/addon/base-addon.d.ts +27 -0
  3. package/dist/addon.js +8 -3
  4. package/dist/addon.mjs +8 -3
  5. package/dist/automation/condition-eval.d.ts +20 -5
  6. package/dist/automation/detection-subject.d.ts +154 -0
  7. package/dist/automation/detection-trigger.d.ts +16 -6
  8. package/dist/automation/index.d.ts +10 -4
  9. package/dist/automation/legacy-recipe.d.ts +130 -0
  10. package/dist/automation/normalize-units.d.ts +4 -3
  11. package/dist/automation/recipe.d.ts +286 -142
  12. package/dist/automation/stationary-trigger.d.ts +4 -4
  13. package/dist/automation/step-runner.d.ts +3 -1
  14. package/dist/automation/trace.d.ts +51 -6
  15. package/dist/automation/when.d.ts +295 -0
  16. package/dist/capabilities/actions.cap.d.ts +10 -0
  17. package/dist/capabilities/addon-settings.cap.d.ts +18 -0
  18. package/dist/capabilities/core-blocks.cap.d.ts +2546 -51
  19. package/dist/capabilities/device-discovery.cap.d.ts +2 -0
  20. package/dist/capabilities/device-manager.cap.d.ts +16 -1
  21. package/dist/capabilities/device-provider.cap.d.ts +165 -0
  22. package/dist/capabilities/index.d.ts +3 -3
  23. package/dist/capabilities/integrations.cap.d.ts +1 -0
  24. package/dist/capabilities/keychain.cap.d.ts +12 -0
  25. package/dist/capabilities/local-network.cap.d.ts +198 -0
  26. package/dist/capabilities/storage-admin.cap.d.ts +155 -0
  27. package/dist/capabilities/terminal-session.cap.d.ts +7 -0
  28. package/dist/client.js +8 -1
  29. package/dist/client.mjs +8 -1
  30. package/dist/device/base-device-provider.d.ts +17 -0
  31. package/dist/generated/addon-api.d.ts +84 -0
  32. package/dist/generated/collection-array-methods.d.ts +1 -1
  33. package/dist/generated/method-access-map.d.ts +1 -1
  34. package/dist/generated/system-proxy.d.ts +3 -3
  35. package/dist/index.d.ts +2 -2
  36. package/dist/index.js +1969 -706
  37. package/dist/index.mjs +1934 -703
  38. package/dist/interfaces/addon.d.ts +16 -0
  39. package/dist/interfaces/config-ui-secrets.d.ts +5 -3
  40. package/dist/interfaces/config-ui.d.ts +34 -1
  41. package/dist/{sleep-BSPhInRm.js → sleep-CewR0zRz.js} +125 -6
  42. package/dist/{sleep-63gM_1JR.mjs → sleep-CeyhrcOk.mjs} +125 -6
  43. package/dist/vendor-login-proxy/cookie-jar.d.ts +30 -0
  44. package/dist/vendor-login-proxy/index.d.ts +1 -0
  45. package/dist/vendor-login-proxy/login-proxy.d.ts +6 -0
  46. package/dist/vendor-login-proxy/url-rewrite.d.ts +9 -2
  47. package/package.json +1 -1
@@ -9,146 +9,23 @@
9
9
  * engine, no second store and no second runtime — the block runner is the
10
10
  * runtime, `core_blocks` is the store (§2.1).
11
11
  *
12
- * Three vocabularies, each salvaged rather than invented:
12
+ * Two parts:
13
13
  *
14
- * - **Triggers** — the only genuinely new surface. Seven members, none of which
15
- * touches notification delivery. The NC keeps its four *pipeline* triggers;
16
- * these are device/time triggers and the two sets do not overlap.
17
- * - **Conditions** — `ALL`/`ANY`/`NOT` over three leaf kinds, bounded. The
18
- * expression leaf is the bounded engine at `../expression/`, which is where
19
- * arithmetic between two device fields lives and the only place it lives.
14
+ * - **`when`** — ONE tree (`./when.ts`) of all/any/not over event leaves
15
+ * (instants) and state leaves (durations). It replaces the flat trigger list
16
+ * plus the separate condition tree; the firing rule is in that file and in
17
+ * ADR "one tree".
20
18
  * - **Actions** — `NcRuleActionSchema`'s two steps, plus the `{kind:'code'}`
21
19
  * fragment of §3.2.2. See {@link AutomationActionSchema} for the ONE place
22
20
  * this had to diverge from "verbatim", and why.
23
21
  *
24
- * Bounds are a guard, not a paragraph (§3.2.1): depth ≤ 3, ≤ 32 leaves. They are
25
- * enforced by {@link validateRecipeBounds} AND by the schema, so a recipe that
26
- * arrives over the wire cannot skip the check that the editor applies.
22
+ * A recipe stored in the old shape (`triggers` + `conditions`) still LOADS:
23
+ * {@link AutomationRecipeSchema} (the parse-anywhere schema) converts it on parse. Nothing writes it.
27
24
  */
28
25
  import { z } from 'zod';
29
- import { type ExpressionBindingSource } from '../expression/binding-source.js';
30
26
  import { type QuantityValue } from '../units/quantity-input.js';
31
- /**
32
- * Depth of a condition tree, counting the root container as level 1.
33
- *
34
- * Three is enough and is not arbitrary: `NOT` over a group is always rewritable
35
- * by De Morgan (`not(any(a,b))` ≡ `all(not a, not b)`), so the shapes that would
36
- * need a fourth level have an equivalent at three. An editor that refuses depth
37
- * 4 should offer that rewrite rather than refusing blankly.
38
- */
39
- export declare const MAX_CONDITION_DEPTH = 3;
40
- /** Leaves per automation. A UI that grows without a bound becomes a language. */
41
- export declare const MAX_CONDITION_LEAVES = 32;
42
- /** How a leaf compares a device field to a value. Derived from the field's
43
- * `kind` in `deviceManager.getWireableFields`, never hand-maintained. */
44
- export declare const AutomationConditionOperatorSchema: z.ZodEnum<{
45
- contains: "contains";
46
- eq: "eq";
47
- gt: "gt";
48
- gte: "gte";
49
- in: "in";
50
- lt: "lt";
51
- lte: "lte";
52
- ne: "ne";
53
- }>;
54
- export type AutomationConditionOperator = z.infer<typeof AutomationConditionOperatorSchema>;
55
- /** A catalog leaf: one device field compared to one value. */
56
- export interface AutomationConditionLeaf {
57
- readonly kind: 'condition';
58
- readonly deviceId: number;
59
- readonly cap: string;
60
- readonly fieldPath: string;
61
- readonly operator: AutomationConditionOperator;
62
- /**
63
- * The value. A number on a quantity field is stored in the field's base unit
64
- * (D944); {@link QuantityValue} is the WRITE form — "this number is in this
65
- * unit" — which the save boundary replaces with the converted number and
66
- * `unit`. A leaf that still carries one is never evaluated (it fails).
67
- */
68
- readonly value: string | number | boolean | readonly (string | number)[] | QuantityValue;
69
- /** The unit the person picked for `value` (display only; `value` is in the base unit). */
70
- readonly unit?: string;
71
- }
72
- /** The escape hatch: the bounded expression engine over named device bindings. */
73
- export interface AutomationConditionExpression {
74
- readonly kind: 'expression';
75
- readonly expr: string;
76
- readonly bindings: Readonly<Record<string, ExpressionBindingSource>>;
77
- }
78
- /**
79
- * True when the camera currently has a PARKED object (stationary registry)
80
- * matching `classes` (macro classes match like the detection trigger) in at
81
- * least one of `zones`. Reads the zone-analytics snapshot through the same
82
- * mirror as every other leaf, so a dropped event never decides it (D49).
83
- */
84
- export interface AutomationConditionStationaryPresent {
85
- readonly kind: 'stationary-present';
86
- readonly deviceId: number;
87
- readonly classes?: readonly string[];
88
- readonly zones?: readonly string[];
89
- }
90
- export interface AutomationConditionAll {
91
- readonly kind: 'all';
92
- readonly children: readonly AutomationCondition[];
93
- }
94
- export interface AutomationConditionAny {
95
- readonly kind: 'any';
96
- readonly children: readonly AutomationCondition[];
97
- }
98
- export interface AutomationConditionNot {
99
- readonly kind: 'not';
100
- readonly child: AutomationCondition;
101
- }
102
- export type AutomationCondition = AutomationConditionAll | AutomationConditionAny | AutomationConditionNot | AutomationConditionLeaf | AutomationConditionExpression | AutomationConditionStationaryPresent;
103
- export declare const AutomationConditionSchema: z.ZodType<AutomationCondition>;
104
- /**
105
- * What starts a run.
106
- *
107
- * D8 compliance, and it is the reason `device-state` is not merely an event
108
- * subscription: the trigger evaluates against the **state mirror**, which is
109
- * reconciled, and an event only WAKES the evaluation. A dropped event therefore
110
- * DELAYS a trigger; it does not lose it. `schedule` uses `croner` — the one
111
- * already in the repo — because `setInterval(24h)` drifts and "at 23:30" does
112
- * not.
113
- */
114
- export declare const AutomationTriggerSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
115
- kind: z.ZodLiteral<"device-state">;
116
- deviceId: z.ZodNumber;
117
- cap: z.ZodString;
118
- fieldPath: z.ZodString;
119
- becomes: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
120
- edge: z.ZodOptional<z.ZodBoolean>;
121
- forMs: z.ZodOptional<z.ZodNumber>;
122
- debounceMs: z.ZodOptional<z.ZodNumber>;
123
- }, z.core.$strip>, z.ZodObject<{
124
- kind: z.ZodLiteral<"device-event">;
125
- category: z.ZodString;
126
- deviceId: z.ZodOptional<z.ZodNumber>;
127
- }, z.core.$strip>, z.ZodObject<{
128
- kind: z.ZodLiteral<"schedule">;
129
- cron: z.ZodString;
130
- }, z.core.$strip>, z.ZodObject<{
131
- kind: z.ZodLiteral<"manual">;
132
- }, z.core.$strip>, z.ZodObject<{
133
- kind: z.ZodLiteral<"detection">;
134
- classes: z.ZodArray<z.ZodString>;
135
- deviceIds: z.ZodArray<z.ZodNumber>;
136
- zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
137
- minScore: z.ZodOptional<z.ZodNumber>;
138
- }, z.core.$strip>, z.ZodObject<{
139
- kind: z.ZodLiteral<"stationary">;
140
- deviceIds: z.ZodArray<z.ZodNumber>;
141
- classes: z.ZodOptional<z.ZodArray<z.ZodString>>;
142
- zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
143
- phase: z.ZodEnum<{
144
- appeared: "appeared";
145
- departed: "departed";
146
- }>;
147
- }, z.core.$strip>, z.ZodObject<{
148
- kind: z.ZodLiteral<"interval">;
149
- minutes: z.ZodNumber;
150
- }, z.core.$strip>], "kind">;
151
- export type AutomationTrigger = z.infer<typeof AutomationTriggerSchema>;
27
+ import { type AutomationWhen } from './when.js';
28
+ export type { QuantityValue };
152
29
  /**
153
30
  * One action step.
154
31
  *
@@ -252,7 +129,47 @@ export type AutomationRunMode = z.infer<typeof AutomationRunModeSchema>;
252
129
  /** Run traces kept per automation when the recipe does not say. */
253
130
  export declare const DEFAULT_TRACE_KEEP = 20;
254
131
  export declare const MAX_TRACE_KEEP = 100;
255
- export declare const AutomationRecipeSchema: z.ZodObject<{
132
+ export declare const CurrentAutomationRecipeSchema: z.ZodObject<{
133
+ when: z.ZodType<AutomationWhen, unknown, z.core.$ZodTypeInternals<AutomationWhen, unknown>>;
134
+ actions: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
135
+ kind: z.ZodLiteral<"wait">;
136
+ seconds: z.ZodNumber;
137
+ }, z.core.$strip>, z.ZodObject<{
138
+ kind: z.ZodLiteral<"cap">;
139
+ deviceId: z.ZodUnion<readonly [z.ZodNumber, z.ZodArray<z.ZodNumber>, z.ZodObject<{
140
+ $var: z.ZodString;
141
+ }, z.core.$strip>]>;
142
+ cap: z.ZodString;
143
+ method: z.ZodString;
144
+ args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
145
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
146
+ }, z.core.$strip>, z.ZodObject<{
147
+ kind: z.ZodLiteral<"action">;
148
+ actionId: z.ZodString;
149
+ variables: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
150
+ }, z.core.$strip>, z.ZodObject<{
151
+ kind: z.ZodLiteral<"code">;
152
+ code: z.ZodString;
153
+ }, z.core.$strip>], "kind">>;
154
+ runMode: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
155
+ mode: z.ZodLiteral<"single">;
156
+ }, z.core.$strip>, z.ZodObject<{
157
+ mode: z.ZodLiteral<"restart">;
158
+ }, z.core.$strip>, z.ZodObject<{
159
+ mode: z.ZodLiteral<"queued">;
160
+ max: z.ZodNumber;
161
+ }, z.core.$strip>, z.ZodObject<{
162
+ mode: z.ZodLiteral<"parallel">;
163
+ max: z.ZodNumber;
164
+ }, z.core.$strip>, z.ZodObject<{
165
+ mode: z.ZodLiteral<"cooldown">;
166
+ minutes: z.ZodNumber;
167
+ }, z.core.$strip>], "mode">>;
168
+ keepTraces: z.ZodOptional<z.ZodNumber>;
169
+ }, z.core.$strip>;
170
+ export type AutomationRecipe = z.infer<typeof CurrentAutomationRecipeSchema>;
171
+ /** A recipe as it was stored before the single tree. Read-only: nothing writes this. */
172
+ export declare const LegacyAutomationRecipeSchema: z.ZodObject<{
256
173
  triggers: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
257
174
  kind: z.ZodLiteral<"device-state">;
258
175
  deviceId: z.ZodNumber;
@@ -290,7 +207,7 @@ export declare const AutomationRecipeSchema: z.ZodObject<{
290
207
  kind: z.ZodLiteral<"interval">;
291
208
  minutes: z.ZodNumber;
292
209
  }, z.core.$strip>], "kind">>;
293
- conditions: z.ZodOptional<z.ZodType<AutomationCondition, unknown, z.core.$ZodTypeInternals<AutomationCondition, unknown>>>;
210
+ conditions: z.ZodOptional<z.ZodType<import("./legacy-recipe.js").LegacyCondition, unknown, z.core.$ZodTypeInternals<import("./legacy-recipe.js").LegacyCondition, unknown>>>;
294
211
  actions: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
295
212
  kind: z.ZodLiteral<"wait">;
296
213
  seconds: z.ZodNumber;
@@ -327,14 +244,241 @@ export declare const AutomationRecipeSchema: z.ZodObject<{
327
244
  }, z.core.$strip>], "mode">>;
328
245
  keepTraces: z.ZodOptional<z.ZodNumber>;
329
246
  }, z.core.$strip>;
330
- export type AutomationRecipe = z.infer<typeof AutomationRecipeSchema>;
331
- /** Depth of a tree, root container = 1. A bare leaf is depth 1. */
332
- export declare function conditionDepth(cond: AutomationCondition): number;
333
- /** Leaves only — containers do not count toward the leaf budget. */
334
- export declare function countConditionLeaves(cond: AutomationCondition): number;
247
+ export type LegacyAutomationRecipe = z.infer<typeof LegacyAutomationRecipeSchema>;
248
+ /** The old shape as the new one, lossless. */
249
+ export declare function convertLegacyRecipe(legacy: LegacyAutomationRecipe): AutomationRecipe;
250
+ /**
251
+ * Where recipes are PARSED (the core-blocks cap, the MCP tool, the literal a
252
+ * saved block carries): the new shape as it is, or the old shape converted to
253
+ * it. The output type is always the new one.
254
+ */
255
+ export declare const AutomationRecipeSchema: z.ZodUnion<readonly [z.ZodObject<{
256
+ when: z.ZodType<AutomationWhen, unknown, z.core.$ZodTypeInternals<AutomationWhen, unknown>>;
257
+ actions: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
258
+ kind: z.ZodLiteral<"wait">;
259
+ seconds: z.ZodNumber;
260
+ }, z.core.$strip>, z.ZodObject<{
261
+ kind: z.ZodLiteral<"cap">;
262
+ deviceId: z.ZodUnion<readonly [z.ZodNumber, z.ZodArray<z.ZodNumber>, z.ZodObject<{
263
+ $var: z.ZodString;
264
+ }, z.core.$strip>]>;
265
+ cap: z.ZodString;
266
+ method: z.ZodString;
267
+ args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
268
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
269
+ }, z.core.$strip>, z.ZodObject<{
270
+ kind: z.ZodLiteral<"action">;
271
+ actionId: z.ZodString;
272
+ variables: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
273
+ }, z.core.$strip>, z.ZodObject<{
274
+ kind: z.ZodLiteral<"code">;
275
+ code: z.ZodString;
276
+ }, z.core.$strip>], "kind">>;
277
+ runMode: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
278
+ mode: z.ZodLiteral<"single">;
279
+ }, z.core.$strip>, z.ZodObject<{
280
+ mode: z.ZodLiteral<"restart">;
281
+ }, z.core.$strip>, z.ZodObject<{
282
+ mode: z.ZodLiteral<"queued">;
283
+ max: z.ZodNumber;
284
+ }, z.core.$strip>, z.ZodObject<{
285
+ mode: z.ZodLiteral<"parallel">;
286
+ max: z.ZodNumber;
287
+ }, z.core.$strip>, z.ZodObject<{
288
+ mode: z.ZodLiteral<"cooldown">;
289
+ minutes: z.ZodNumber;
290
+ }, z.core.$strip>], "mode">>;
291
+ keepTraces: z.ZodOptional<z.ZodNumber>;
292
+ }, z.core.$strip>, z.ZodPipe<z.ZodObject<{
293
+ triggers: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
294
+ kind: z.ZodLiteral<"device-state">;
295
+ deviceId: z.ZodNumber;
296
+ cap: z.ZodString;
297
+ fieldPath: z.ZodString;
298
+ becomes: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
299
+ edge: z.ZodOptional<z.ZodBoolean>;
300
+ forMs: z.ZodOptional<z.ZodNumber>;
301
+ debounceMs: z.ZodOptional<z.ZodNumber>;
302
+ }, z.core.$strip>, z.ZodObject<{
303
+ kind: z.ZodLiteral<"device-event">;
304
+ category: z.ZodString;
305
+ deviceId: z.ZodOptional<z.ZodNumber>;
306
+ }, z.core.$strip>, z.ZodObject<{
307
+ kind: z.ZodLiteral<"schedule">;
308
+ cron: z.ZodString;
309
+ }, z.core.$strip>, z.ZodObject<{
310
+ kind: z.ZodLiteral<"manual">;
311
+ }, z.core.$strip>, z.ZodObject<{
312
+ kind: z.ZodLiteral<"detection">;
313
+ classes: z.ZodArray<z.ZodString>;
314
+ deviceIds: z.ZodArray<z.ZodNumber>;
315
+ zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
316
+ minScore: z.ZodOptional<z.ZodNumber>;
317
+ }, z.core.$strip>, z.ZodObject<{
318
+ kind: z.ZodLiteral<"stationary">;
319
+ deviceIds: z.ZodArray<z.ZodNumber>;
320
+ classes: z.ZodOptional<z.ZodArray<z.ZodString>>;
321
+ zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
322
+ phase: z.ZodEnum<{
323
+ appeared: "appeared";
324
+ departed: "departed";
325
+ }>;
326
+ }, z.core.$strip>, z.ZodObject<{
327
+ kind: z.ZodLiteral<"interval">;
328
+ minutes: z.ZodNumber;
329
+ }, z.core.$strip>], "kind">>;
330
+ conditions: z.ZodOptional<z.ZodType<import("./legacy-recipe.js").LegacyCondition, unknown, z.core.$ZodTypeInternals<import("./legacy-recipe.js").LegacyCondition, unknown>>>;
331
+ actions: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
332
+ kind: z.ZodLiteral<"wait">;
333
+ seconds: z.ZodNumber;
334
+ }, z.core.$strip>, z.ZodObject<{
335
+ kind: z.ZodLiteral<"cap">;
336
+ deviceId: z.ZodUnion<readonly [z.ZodNumber, z.ZodArray<z.ZodNumber>, z.ZodObject<{
337
+ $var: z.ZodString;
338
+ }, z.core.$strip>]>;
339
+ cap: z.ZodString;
340
+ method: z.ZodString;
341
+ args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
342
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
343
+ }, z.core.$strip>, z.ZodObject<{
344
+ kind: z.ZodLiteral<"action">;
345
+ actionId: z.ZodString;
346
+ variables: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
347
+ }, z.core.$strip>, z.ZodObject<{
348
+ kind: z.ZodLiteral<"code">;
349
+ code: z.ZodString;
350
+ }, z.core.$strip>], "kind">>;
351
+ runMode: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
352
+ mode: z.ZodLiteral<"single">;
353
+ }, z.core.$strip>, z.ZodObject<{
354
+ mode: z.ZodLiteral<"restart">;
355
+ }, z.core.$strip>, z.ZodObject<{
356
+ mode: z.ZodLiteral<"queued">;
357
+ max: z.ZodNumber;
358
+ }, z.core.$strip>, z.ZodObject<{
359
+ mode: z.ZodLiteral<"parallel">;
360
+ max: z.ZodNumber;
361
+ }, z.core.$strip>, z.ZodObject<{
362
+ mode: z.ZodLiteral<"cooldown">;
363
+ minutes: z.ZodNumber;
364
+ }, z.core.$strip>], "mode">>;
365
+ keepTraces: z.ZodOptional<z.ZodNumber>;
366
+ }, z.core.$strip>, z.ZodTransform<{
367
+ when: AutomationWhen;
368
+ actions: ({
369
+ kind: "cap";
370
+ deviceId: number | number[] | {
371
+ $var: string;
372
+ };
373
+ cap: string;
374
+ method: string;
375
+ args?: Record<string, unknown> | undefined;
376
+ argUnits?: Record<string, string> | undefined;
377
+ } | {
378
+ kind: "wait";
379
+ seconds: number;
380
+ } | {
381
+ kind: "action";
382
+ actionId: string;
383
+ variables?: Record<string, string | number | boolean> | undefined;
384
+ } | {
385
+ kind: "code";
386
+ code: string;
387
+ })[];
388
+ runMode?: {
389
+ mode: "single";
390
+ } | {
391
+ mode: "restart";
392
+ } | {
393
+ mode: "queued";
394
+ max: number;
395
+ } | {
396
+ mode: "parallel";
397
+ max: number;
398
+ } | {
399
+ mode: "cooldown";
400
+ minutes: number;
401
+ } | undefined;
402
+ keepTraces?: number | undefined;
403
+ }, {
404
+ triggers: ({
405
+ kind: "device-state";
406
+ deviceId: number;
407
+ cap: string;
408
+ fieldPath: string;
409
+ becomes?: string | number | boolean | undefined;
410
+ edge?: boolean | undefined;
411
+ forMs?: number | undefined;
412
+ debounceMs?: number | undefined;
413
+ } | {
414
+ kind: "device-event";
415
+ category: string;
416
+ deviceId?: number | undefined;
417
+ } | {
418
+ kind: "schedule";
419
+ cron: string;
420
+ } | {
421
+ kind: "manual";
422
+ } | {
423
+ kind: "detection";
424
+ classes: string[];
425
+ deviceIds: number[];
426
+ zones?: string[] | undefined;
427
+ minScore?: number | undefined;
428
+ } | {
429
+ kind: "stationary";
430
+ deviceIds: number[];
431
+ classes?: string[] | undefined;
432
+ zones?: string[] | undefined;
433
+ phase: "appeared" | "departed";
434
+ } | {
435
+ kind: "interval";
436
+ minutes: number;
437
+ })[];
438
+ conditions?: import("./legacy-recipe.js").LegacyCondition | undefined;
439
+ actions: ({
440
+ kind: "cap";
441
+ deviceId: number | number[] | {
442
+ $var: string;
443
+ };
444
+ cap: string;
445
+ method: string;
446
+ args?: Record<string, unknown> | undefined;
447
+ argUnits?: Record<string, string> | undefined;
448
+ } | {
449
+ kind: "wait";
450
+ seconds: number;
451
+ } | {
452
+ kind: "action";
453
+ actionId: string;
454
+ variables?: Record<string, string | number | boolean> | undefined;
455
+ } | {
456
+ kind: "code";
457
+ code: string;
458
+ })[];
459
+ runMode?: {
460
+ mode: "single";
461
+ } | {
462
+ mode: "restart";
463
+ } | {
464
+ mode: "queued";
465
+ max: number;
466
+ } | {
467
+ mode: "parallel";
468
+ max: number;
469
+ } | {
470
+ mode: "cooldown";
471
+ minutes: number;
472
+ } | undefined;
473
+ keepTraces?: number | undefined;
474
+ }>>]>;
475
+ /** Bounds, shared by `when` and the old names the guards still know. */
476
+ export declare const MAX_CONDITION_DEPTH = 4;
477
+ export declare const MAX_CONDITION_LEAVES = 32;
335
478
  /**
336
- * Author-time bounds check. Returns `null` when the recipe is legal, else a
337
- * message naming the bound it broke — the editor shows it verbatim, so it has
338
- * to read like something an operator can act on.
479
+ * Author-time check. Returns `null` when the recipe is legal, else a message
480
+ * naming what is wrong — the editor shows it verbatim, so it has to read like
481
+ * something an operator can act on.
339
482
  */
340
483
  export declare function validateRecipeBounds(recipe: AutomationRecipe): string | null;
484
+ export type { AutomationWhen };
@@ -13,10 +13,10 @@
13
13
  * misses a fire, and nothing durable depends on it.
14
14
  */
15
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
- }>;
16
+ import type { LegacyStationaryTrigger } from './legacy-recipe.js';
17
+ import type { StationaryLeaf } from './when.js';
18
+ /** A stationary leaf — or the old trigger a block generated before the single tree still hands over. */
19
+ export type StationaryTrigger = StationaryLeaf | LegacyStationaryTrigger;
20
20
  /** The fields of a stationary-changed event the trigger reads (all `unknown`: off the bus). */
21
21
  export interface StationaryChangedInput {
22
22
  readonly deviceId?: unknown;
@@ -9,7 +9,7 @@
9
9
  * after a failure, or after an abort, are `not-run` with the reason.
10
10
  */
11
11
  import type { ActionStep } from './recipe.js';
12
- import type { AutomationStepTrace } from './trace.js';
12
+ import { type AutomationStepTrace } from './trace.js';
13
13
  /** Static facts about a step, known before it runs. */
14
14
  export interface StepMeta {
15
15
  readonly kind: string;
@@ -20,6 +20,8 @@ export interface StepMeta {
20
20
  /** What a running step can tell the runner (the device a fan-out is on right now). */
21
21
  export interface StepScope {
22
22
  setDeviceId(deviceId: number): void;
23
+ /** The parameters the step is sending NOW (substituted), for its trace. */
24
+ setArgs(args: Readonly<Record<string, unknown>>): void;
23
25
  }
24
26
  /** One step as the runner sees it: its meta and a closure that does the work. */
25
27
  export interface RunnableStep {
@@ -2,11 +2,12 @@
2
2
  * Run traces — what an automation (or, later, an Action run) DID, node by node,
3
3
  * so the editor can paint every block green or red with its reason.
4
4
  *
5
- * A trace is data, not a log: it covers the WHOLE tree — the trigger stage,
6
- * every condition node (containers and leaves, including the ones a
7
- * short-circuit never reached), the run-mode verdict and every action step —
8
- * each addressed by a stable path (`conditions.0.1`, `actions.2`, or `steps.N`
9
- * for an Action run). Skipped
5
+ * A trace is data, not a log: it covers the WHOLE tree — the event leaf that
6
+ * fired, every node of the `when` tree (containers and leaves, including the
7
+ * ones a short-circuit never reached), the run-mode verdict and every action
8
+ * step — each addressed by a stable path (`when.0.1`, `actions.2`, or `steps.N`
9
+ * for an Action run). Traces written before the single tree carry
10
+ * `conditions.*` paths and still parse. Skipped
10
11
  * evaluations are traced too, and identical consecutive skips collapse into a
11
12
  * repeat count so a trigger that fails every 5 minutes cannot flush real runs.
12
13
  *
@@ -36,6 +37,7 @@ export declare const TraceNodeOutcomeSchema: z.ZodEnum<{
36
37
  export type TraceNodeOutcome = z.infer<typeof TraceNodeOutcomeSchema>;
37
38
  export declare const AutomationTriggerTraceSchema: z.ZodObject<{
38
39
  kind: z.ZodString;
40
+ path: z.ZodOptional<z.ZodString>;
39
41
  outcome: z.ZodEnum<{
40
42
  fail: "fail";
41
43
  pass: "pass";
@@ -50,8 +52,16 @@ export declare const AutomationConditionTraceNodeSchema: z.ZodObject<{
50
52
  all: "all";
51
53
  any: "any";
52
54
  condition: "condition";
55
+ detection: "detection";
56
+ "device-becomes": "device-becomes";
57
+ "device-event": "device-event";
58
+ "device-is": "device-is";
53
59
  expression: "expression";
60
+ interval: "interval";
61
+ manual: "manual";
54
62
  not: "not";
63
+ schedule: "schedule";
64
+ stationary: "stationary";
55
65
  "stationary-present": "stationary-present";
56
66
  }>;
57
67
  outcome: z.ZodEnum<{
@@ -103,6 +113,7 @@ export declare const AutomationStepTraceSchema: z.ZodObject<{
103
113
  deviceId: z.ZodOptional<z.ZodNumber>;
104
114
  startedAt: z.ZodOptional<z.ZodNumber>;
105
115
  endedAt: z.ZodOptional<z.ZodNumber>;
116
+ args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>]>>>;
106
117
  outcome: z.ZodEnum<{
107
118
  error: "error";
108
119
  "not-run": "not-run";
@@ -117,6 +128,7 @@ export declare const AutomationRunTraceSchema: z.ZodObject<{
117
128
  endedAt: z.ZodNumber;
118
129
  trigger: z.ZodObject<{
119
130
  kind: z.ZodString;
131
+ path: z.ZodOptional<z.ZodString>;
120
132
  outcome: z.ZodEnum<{
121
133
  fail: "fail";
122
134
  pass: "pass";
@@ -130,8 +142,16 @@ export declare const AutomationRunTraceSchema: z.ZodObject<{
130
142
  all: "all";
131
143
  any: "any";
132
144
  condition: "condition";
145
+ detection: "detection";
146
+ "device-becomes": "device-becomes";
147
+ "device-event": "device-event";
148
+ "device-is": "device-is";
133
149
  expression: "expression";
150
+ interval: "interval";
151
+ manual: "manual";
134
152
  not: "not";
153
+ schedule: "schedule";
154
+ stationary: "stationary";
135
155
  "stationary-present": "stationary-present";
136
156
  }>;
137
157
  outcome: z.ZodEnum<{
@@ -180,6 +200,7 @@ export declare const AutomationRunTraceSchema: z.ZodObject<{
180
200
  deviceId: z.ZodOptional<z.ZodNumber>;
181
201
  startedAt: z.ZodOptional<z.ZodNumber>;
182
202
  endedAt: z.ZodOptional<z.ZodNumber>;
203
+ args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>]>>>;
183
204
  outcome: z.ZodEnum<{
184
205
  error: "error";
185
206
  "not-run": "not-run";
@@ -213,6 +234,7 @@ export declare const AutomationStateDocSchema: z.ZodObject<{
213
234
  endedAt: z.ZodNumber;
214
235
  trigger: z.ZodObject<{
215
236
  kind: z.ZodString;
237
+ path: z.ZodOptional<z.ZodString>;
216
238
  outcome: z.ZodEnum<{
217
239
  fail: "fail";
218
240
  pass: "pass";
@@ -226,8 +248,16 @@ export declare const AutomationStateDocSchema: z.ZodObject<{
226
248
  all: "all";
227
249
  any: "any";
228
250
  condition: "condition";
251
+ detection: "detection";
252
+ "device-becomes": "device-becomes";
253
+ "device-event": "device-event";
254
+ "device-is": "device-is";
229
255
  expression: "expression";
256
+ interval: "interval";
257
+ manual: "manual";
230
258
  not: "not";
259
+ schedule: "schedule";
260
+ stationary: "stationary";
231
261
  "stationary-present": "stationary-present";
232
262
  }>;
233
263
  outcome: z.ZodEnum<{
@@ -276,6 +306,7 @@ export declare const AutomationStateDocSchema: z.ZodObject<{
276
306
  deviceId: z.ZodOptional<z.ZodNumber>;
277
307
  startedAt: z.ZodOptional<z.ZodNumber>;
278
308
  endedAt: z.ZodOptional<z.ZodNumber>;
309
+ args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>]>>>;
279
310
  outcome: z.ZodEnum<{
280
311
  error: "error";
281
312
  "not-run": "not-run";
@@ -320,9 +351,23 @@ export declare function mergeSkipTraces(prev: AutomationRunTrace, next: Automati
320
351
  * cannot push the runs the operator is looking for out of the ring.
321
352
  */
322
353
  export declare function appendTrace(ring: readonly AutomationRunTrace[], trace: AutomationRunTrace, keep: number): AutomationRunTrace[];
354
+ /** What a secret parameter is shown as in a trace. */
355
+ export declare const REDACTED_ARG = "[redacted]";
356
+ /** Parameters kept per step trace; the rest are counted in `…`. */
357
+ export declare const MAX_TRACE_ARGS = 32;
358
+ /** A string value is cut here. */
359
+ export declare const MAX_TRACE_ARG_LENGTH = 200;
360
+ /**
361
+ * The parameters a step sent, as a trace may show them: primitives and short
362
+ * lists of them (anything deeper is its JSON text, cut), at most
363
+ * {@link MAX_TRACE_ARGS} of them. No cap method declares a parameter secret, so
364
+ * a parameter is redacted by what it is called or by being a keychain marker,
365
+ * and `secretKeys` names the ones a caller knows about.
366
+ */
367
+ export declare function buildStepArgsTrace(args: Readonly<Record<string, unknown>>, secretKeys?: readonly string[]): Record<string, TraceValue>;
323
368
  /**
324
369
  * The trigger stage of a trace from the bag a trigger handed to `run()`:
325
370
  * primitives and short lists of them (a device-state `to` that is an object is left out), minus the
326
- * bookkeeping keys `kind` and `at`.
371
+ * bookkeeping keys `kind`, `at` and `leaf` (the fired leaf's path, which moves to `path`).
327
372
  */
328
373
  export declare function buildTriggerTrace(trigger: Readonly<Record<string, unknown>>, outcome: 'pass' | 'fail', reason: string): AutomationTriggerTrace;