@camstack/types 1.2.446 → 1.2.447

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,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.2.447] - 2026-10-29
11
+
12
+ ### Changed
13
+
14
+ - Numbers tied to a physical quantity can be entered in a unit you pick: automation conditions and steps accept { value, unit }, converted to the stored unit, and a bare API number is accepted with a warning
15
+
10
16
  ## [1.2.446] - 2026-10-29
11
17
 
12
18
  ### Changed
@@ -92,6 +92,7 @@ export declare const ActionEntrySchema: z.ZodObject<{
92
92
  cap: z.ZodString;
93
93
  method: z.ZodString;
94
94
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
95
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
95
96
  }, z.core.$strip>], "kind">>>;
96
97
  variables: z.ZodOptional<z.ZodArray<z.ZodObject<{
97
98
  name: z.ZodString;
@@ -127,6 +128,7 @@ export declare const ActionInputSchema: z.ZodObject<{
127
128
  cap: z.ZodString;
128
129
  method: z.ZodString;
129
130
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
131
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
130
132
  }, z.core.$strip>], "kind">>;
131
133
  variables: z.ZodOptional<z.ZodArray<z.ZodObject<{
132
134
  name: z.ZodString;
@@ -20,7 +20,9 @@ export type { CooldownInput, CooldownVerdict, RunGateAdmission } from './run-gat
20
20
  export { RunGate } from './run-gate.js';
21
21
  export type { AutomationConditionTraceNode, AutomationRunOutcome, AutomationRunTrace, AutomationRunVerdict, AutomationStateDoc, AutomationStepTrace, AutomationTriggerTrace, TraceNodeOutcome, TraceValue, } from './trace.js';
22
22
  export { AutomationConditionTraceNodeSchema, EMPTY_AUTOMATION_STATE, mergeSkipTraces, AutomationRunOutcomeSchema, AutomationRunTraceSchema, AutomationRunVerdictSchema, AutomationStateDocSchema, AutomationStepTraceSchema, AutomationTriggerTraceSchema, appendTrace, buildTriggerTrace, isSkippedTrace, skipSignature, TraceNodeOutcomeSchema, TraceValueSchema, } from './trace.js';
23
- export type { ActionStep, AutomationAction, AutomationCondition, AutomationConditionAll, AutomationConditionAny, AutomationConditionExpression, AutomationConditionLeaf, AutomationConditionNot, AutomationConditionOperator, AutomationConditionStationaryPresent, AutomationRecipe, AutomationRunMode, AutomationTrigger, } from './recipe.js';
23
+ export type { ActionStep, AutomationAction, AutomationCapStep, AutomationCondition, AutomationConditionAll, AutomationConditionAny, AutomationConditionExpression, AutomationConditionLeaf, AutomationConditionNot, AutomationConditionOperator, AutomationConditionStationaryPresent, AutomationRecipe, AutomationRunMode, AutomationTrigger, } from './recipe.js';
24
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';
25
25
  export * from './action.js';
26
26
  export * from './step-runner.js';
27
+ export { UnitWarningSchema, capUnitResolver, normalizeActionUnits, normalizeConditionUnits, normalizeRecipeUnits, } from './normalize-units.js';
28
+ export type { UnitResolver, UnitWarning, UnitsNormalized } from './normalize-units.js';
@@ -0,0 +1,59 @@
1
+ /**
2
+ * The save boundary of the value + unit contract (D972).
3
+ *
4
+ * A number tied to a physical quantity is ENTERED in a unit the person picks
5
+ * and STORED in a fixed one:
6
+ *
7
+ * - a condition leaf on a device field → the field's base unit (D944);
8
+ * - a cap step arg → the unit the method's input declares (`paramMeta`).
9
+ *
10
+ * The write form of a number is {@link QuantityValue} (`{ value, unit }`,
11
+ * "this number is in this unit"). Normalising converts it, stores the bare
12
+ * number and records the picked unit (`leaf.unit` / `step.argUnits[arg]`) so an
13
+ * editor can show the number the way it was typed. Normalising an already
14
+ * normalised record changes nothing: a stored bare number is never converted
15
+ * again, which is why the picked unit is a separate field.
16
+ *
17
+ * A bare number on a quantity field is ACCEPTED as the base / declared unit
18
+ * and reported as a {@link UnitWarning}; a unit that cannot belong to the
19
+ * quantity is a typed {@link QuantityUnitError}.
20
+ *
21
+ * Pure: the cap knowledge arrives as a {@link UnitResolver}.
22
+ */
23
+ import type { CapabilityDefinition } from '../capabilities/capability-definition.js';
24
+ import { type ParamMeta } from '../units/quantity-input.js';
25
+ import type { ReadingQuantity } from '../units/quantity.js';
26
+ import { z } from 'zod';
27
+ import type { AutomationAction, AutomationCapStep, AutomationCondition, AutomationRecipe } from './recipe.js';
28
+ /** What the boundary needs to know about caps. */
29
+ export interface UnitResolver {
30
+ /** The quantity of a status field, or `undefined` when it is not a quantity. */
31
+ fieldQuantity(cap: string, fieldPath: string): ReadingQuantity | undefined;
32
+ /** What a method input declares for `arg`, or `undefined` when it is not a quantity. */
33
+ paramMeta(cap: string, method: string, arg: string): ParamMeta | undefined;
34
+ }
35
+ /** A bare number accepted as a base unit — the save succeeded, say so. */
36
+ export declare const UnitWarningSchema: z.ZodObject<{
37
+ path: z.ZodString;
38
+ deviceId: z.ZodOptional<z.ZodNumber>;
39
+ field: z.ZodString;
40
+ value: z.ZodNumber;
41
+ assumedUnit: z.ZodString;
42
+ message: z.ZodString;
43
+ }, z.core.$strip>;
44
+ export type UnitWarning = z.infer<typeof UnitWarningSchema>;
45
+ export interface UnitsNormalized<T> {
46
+ readonly value: T;
47
+ readonly warnings: readonly UnitWarning[];
48
+ }
49
+ /** A resolver over capability definitions (the generated registry, or a fake). */
50
+ export declare function capUnitResolver(defs: readonly CapabilityDefinition[]): UnitResolver;
51
+ /** Normalise every leaf of a condition tree. Throws {@link QuantityUnitError}. */
52
+ export declare function normalizeConditionUnits(condition: AutomationCondition, resolver: UnitResolver, path?: string): UnitsNormalized<AutomationCondition>;
53
+ /**
54
+ * Normalise the cap steps of an action list (an internal Action's steps, or a
55
+ * recipe's actions). Other step kinds pass through. Throws {@link QuantityUnitError}.
56
+ */
57
+ export declare function normalizeActionUnits<A extends AutomationAction>(actions: readonly A[], resolver: UnitResolver, path?: string): UnitsNormalized<(A | AutomationCapStep)[]>;
58
+ /** Normalise a whole recipe: its condition tree and its actions. */
59
+ export declare function normalizeRecipeUnits(recipe: AutomationRecipe, resolver: UnitResolver): UnitsNormalized<AutomationRecipe>;
@@ -27,6 +27,7 @@
27
27
  */
28
28
  import { z } from 'zod';
29
29
  import { type ExpressionBindingSource } from '../expression/binding-source.js';
30
+ import { type QuantityValue } from '../units/quantity-input.js';
30
31
  /**
31
32
  * Depth of a condition tree, counting the root container as level 1.
32
33
  *
@@ -58,7 +59,15 @@ export interface AutomationConditionLeaf {
58
59
  readonly cap: string;
59
60
  readonly fieldPath: string;
60
61
  readonly operator: AutomationConditionOperator;
61
- readonly value: string | number | boolean | readonly (string | number)[];
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;
62
71
  }
63
72
  /** The escape hatch: the bounded expression engine over named device bindings. */
64
73
  export interface AutomationConditionExpression {
@@ -170,7 +179,9 @@ export declare const AutomationCapStepSchema: z.ZodObject<{
170
179
  cap: z.ZodString;
171
180
  method: z.ZodString;
172
181
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
182
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
173
183
  }, z.core.$strip>;
184
+ export type AutomationCapStep = z.infer<typeof AutomationCapStepSchema>;
174
185
  /**
175
186
  * The steps an internal Action may contain: cap and wait, and nothing that can
176
187
  * call back into an Action — so an Action can never reach itself (no cycles).
@@ -186,6 +197,7 @@ export declare const ActionStepSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
186
197
  cap: z.ZodString;
187
198
  method: z.ZodString;
188
199
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
200
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
189
201
  }, z.core.$strip>], "kind">;
190
202
  export type ActionStep = z.infer<typeof ActionStepSchema>;
191
203
  export declare const AutomationActionSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
@@ -199,6 +211,7 @@ export declare const AutomationActionSchema: z.ZodDiscriminatedUnion<[z.ZodObjec
199
211
  cap: z.ZodString;
200
212
  method: z.ZodString;
201
213
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
214
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
202
215
  }, z.core.$strip>, z.ZodObject<{
203
216
  kind: z.ZodLiteral<"action">;
204
217
  actionId: z.ZodString;
@@ -289,6 +302,7 @@ export declare const AutomationRecipeSchema: z.ZodObject<{
289
302
  cap: z.ZodString;
290
303
  method: z.ZodString;
291
304
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
305
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
292
306
  }, z.core.$strip>, z.ZodObject<{
293
307
  kind: z.ZodLiteral<"action">;
294
308
  actionId: z.ZodString;
@@ -42,6 +42,7 @@ export declare const actionSourceCapability: {
42
42
  cap: z.ZodString;
43
43
  method: z.ZodString;
44
44
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
45
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
45
46
  }, z.core.$strip>], "kind">>>;
46
47
  variables: z.ZodOptional<z.ZodArray<z.ZodObject<{
47
48
  name: z.ZodString;
@@ -31,6 +31,7 @@ export declare const actionsCapability: {
31
31
  cap: z.ZodString;
32
32
  method: z.ZodString;
33
33
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
34
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
34
35
  }, z.core.$strip>], "kind">>>;
35
36
  variables: z.ZodOptional<z.ZodArray<z.ZodObject<{
36
37
  name: z.ZodString;
@@ -79,6 +80,7 @@ export declare const actionsCapability: {
79
80
  cap: z.ZodString;
80
81
  method: z.ZodString;
81
82
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
83
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
82
84
  }, z.core.$strip>], "kind">>>;
83
85
  variables: z.ZodOptional<z.ZodArray<z.ZodObject<{
84
86
  name: z.ZodString;
@@ -225,7 +227,15 @@ export declare const actionsCapability: {
225
227
  lastAt: z.ZodNumber;
226
228
  }, z.core.$strip>>;
227
229
  }, z.core.$strip>, import("./capability-definition.js").CapabilityMethodKind>;
228
- /** Internal actions only. A read-only (addon) entry is refused with `[read-only]`. */
230
+ /**
231
+ * Internal actions only; a read-only (addon) entry is refused with `[read-only]`.
232
+ * Create an internal action. A cap step arg that is a physical quantity may
233
+ * be sent as `{ value, unit }` ("value expressed in unit"); the server
234
+ * converts it to the unit the method's input declares, stores the bare
235
+ * number plus the picked unit in `argUnits`, and refuses a unit of another
236
+ * dimension (`[invalid-steps]`). A bare number is taken as the declared
237
+ * unit and answered as a `warnings` entry (D972).
238
+ */
229
239
  readonly create: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
230
240
  action: z.ZodObject<{
231
241
  name: z.ZodString;
@@ -240,6 +250,7 @@ export declare const actionsCapability: {
240
250
  cap: z.ZodString;
241
251
  method: z.ZodString;
242
252
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
253
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
243
254
  }, z.core.$strip>], "kind">>;
244
255
  variables: z.ZodOptional<z.ZodArray<z.ZodObject<{
245
256
  name: z.ZodString;
@@ -276,6 +287,7 @@ export declare const actionsCapability: {
276
287
  cap: z.ZodString;
277
288
  method: z.ZodString;
278
289
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
290
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
279
291
  }, z.core.$strip>], "kind">>>;
280
292
  variables: z.ZodOptional<z.ZodArray<z.ZodObject<{
281
293
  name: z.ZodString;
@@ -296,6 +308,14 @@ export declare const actionsCapability: {
296
308
  lastError: z.ZodNullable<z.ZodString>;
297
309
  }, z.core.$strip>;
298
310
  }, z.core.$strip>;
311
+ warnings: z.ZodOptional<z.ZodArray<z.ZodObject<{
312
+ path: z.ZodString;
313
+ deviceId: z.ZodOptional<z.ZodNumber>;
314
+ field: z.ZodString;
315
+ value: z.ZodNumber;
316
+ assumedUnit: z.ZodString;
317
+ message: z.ZodString;
318
+ }, z.core.$strip>>>;
299
319
  }, z.core.$strip>, "mutation">;
300
320
  readonly update: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
301
321
  actionId: z.ZodString;
@@ -312,6 +332,7 @@ export declare const actionsCapability: {
312
332
  cap: z.ZodString;
313
333
  method: z.ZodString;
314
334
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
335
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
315
336
  }, z.core.$strip>], "kind">>>;
316
337
  variables: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodObject<{
317
338
  name: z.ZodString;
@@ -348,6 +369,7 @@ export declare const actionsCapability: {
348
369
  cap: z.ZodString;
349
370
  method: z.ZodString;
350
371
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
372
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
351
373
  }, z.core.$strip>], "kind">>>;
352
374
  variables: z.ZodOptional<z.ZodArray<z.ZodObject<{
353
375
  name: z.ZodString;
@@ -368,6 +390,14 @@ export declare const actionsCapability: {
368
390
  lastError: z.ZodNullable<z.ZodString>;
369
391
  }, z.core.$strip>;
370
392
  }, z.core.$strip>;
393
+ warnings: z.ZodOptional<z.ZodArray<z.ZodObject<{
394
+ path: z.ZodString;
395
+ deviceId: z.ZodOptional<z.ZodNumber>;
396
+ field: z.ZodString;
397
+ value: z.ZodNumber;
398
+ assumedUnit: z.ZodString;
399
+ message: z.ZodString;
400
+ }, z.core.$strip>>>;
371
401
  }, z.core.$strip>, "mutation">;
372
402
  readonly delete: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
373
403
  actionId: z.ZodString;
@@ -399,6 +429,7 @@ export declare const actionsCapability: {
399
429
  cap: z.ZodString;
400
430
  method: z.ZodString;
401
431
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
432
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
402
433
  }, z.core.$strip>], "kind">>>;
403
434
  variables: z.ZodOptional<z.ZodArray<z.ZodObject<{
404
435
  name: z.ZodString;
@@ -188,6 +188,7 @@ export declare const CoreBlockSourceSchema: z.ZodDiscriminatedUnion<[z.ZodObject
188
188
  cap: z.ZodString;
189
189
  method: z.ZodString;
190
190
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
191
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
191
192
  }, z.core.$strip>, z.ZodObject<{
192
193
  kind: z.ZodLiteral<"action">;
193
194
  actionId: z.ZodString;
@@ -731,6 +732,7 @@ export declare const CoreBlockSchema: z.ZodObject<{
731
732
  cap: z.ZodString;
732
733
  method: z.ZodString;
733
734
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
735
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
734
736
  }, z.core.$strip>, z.ZodObject<{
735
737
  kind: z.ZodLiteral<"action">;
736
738
  actionId: z.ZodString;
@@ -1090,6 +1092,7 @@ export declare const CompositionViewSchema: z.ZodObject<{
1090
1092
  cap: z.ZodString;
1091
1093
  method: z.ZodString;
1092
1094
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1095
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1093
1096
  }, z.core.$strip>, z.ZodObject<{
1094
1097
  kind: z.ZodLiteral<"action">;
1095
1098
  actionId: z.ZodString;
@@ -1447,6 +1450,7 @@ export declare const CompositionListReadSchema: z.ZodDiscriminatedUnion<[z.ZodOb
1447
1450
  cap: z.ZodString;
1448
1451
  method: z.ZodString;
1449
1452
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1453
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1450
1454
  }, z.core.$strip>, z.ZodObject<{
1451
1455
  kind: z.ZodLiteral<"action">;
1452
1456
  actionId: z.ZodString;
@@ -1808,6 +1812,7 @@ export declare const CompositionGetReadSchema: z.ZodDiscriminatedUnion<[z.ZodObj
1808
1812
  cap: z.ZodString;
1809
1813
  method: z.ZodString;
1810
1814
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1815
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1811
1816
  }, z.core.$strip>, z.ZodObject<{
1812
1817
  kind: z.ZodLiteral<"action">;
1813
1818
  actionId: z.ZodString;
@@ -2170,6 +2175,7 @@ export declare const CompositionCustomizationReadSchema: z.ZodDiscriminatedUnion
2170
2175
  cap: z.ZodString;
2171
2176
  method: z.ZodString;
2172
2177
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
2178
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
2173
2179
  }, z.core.$strip>, z.ZodObject<{
2174
2180
  kind: z.ZodLiteral<"action">;
2175
2181
  actionId: z.ZodString;
@@ -2552,6 +2558,7 @@ export declare const coreBlocksCapability: {
2552
2558
  cap: z.ZodString;
2553
2559
  method: z.ZodString;
2554
2560
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
2561
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
2555
2562
  }, z.core.$strip>, z.ZodObject<{
2556
2563
  kind: z.ZodLiteral<"action">;
2557
2564
  actionId: z.ZodString;
@@ -2872,6 +2879,7 @@ export declare const coreBlocksCapability: {
2872
2879
  cap: z.ZodString;
2873
2880
  method: z.ZodString;
2874
2881
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
2882
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
2875
2883
  }, z.core.$strip>, z.ZodObject<{
2876
2884
  kind: z.ZodLiteral<"action">;
2877
2885
  actionId: z.ZodString;
@@ -3206,6 +3214,7 @@ export declare const coreBlocksCapability: {
3206
3214
  cap: z.ZodString;
3207
3215
  method: z.ZodString;
3208
3216
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
3217
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
3209
3218
  }, z.core.$strip>, z.ZodObject<{
3210
3219
  kind: z.ZodLiteral<"action">;
3211
3220
  actionId: z.ZodString;
@@ -3538,6 +3547,7 @@ export declare const coreBlocksCapability: {
3538
3547
  cap: z.ZodString;
3539
3548
  method: z.ZodString;
3540
3549
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
3550
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
3541
3551
  }, z.core.$strip>, z.ZodObject<{
3542
3552
  kind: z.ZodLiteral<"action">;
3543
3553
  actionId: z.ZodString;
@@ -3866,6 +3876,7 @@ export declare const coreBlocksCapability: {
3866
3876
  cap: z.ZodString;
3867
3877
  method: z.ZodString;
3868
3878
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
3879
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
3869
3880
  }, z.core.$strip>, z.ZodObject<{
3870
3881
  kind: z.ZodLiteral<"action">;
3871
3882
  actionId: z.ZodString;
@@ -4199,6 +4210,7 @@ export declare const coreBlocksCapability: {
4199
4210
  cap: z.ZodString;
4200
4211
  method: z.ZodString;
4201
4212
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
4213
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
4202
4214
  }, z.core.$strip>, z.ZodObject<{
4203
4215
  kind: z.ZodLiteral<"action">;
4204
4216
  actionId: z.ZodString;
@@ -4838,6 +4850,7 @@ export declare const coreBlocksCapability: {
4838
4850
  cap: z.ZodString;
4839
4851
  method: z.ZodString;
4840
4852
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
4853
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
4841
4854
  }, z.core.$strip>, z.ZodObject<{
4842
4855
  kind: z.ZodLiteral<"action">;
4843
4856
  actionId: z.ZodString;
@@ -5381,6 +5394,7 @@ export declare const coreBlocksCapability: {
5381
5394
  cap: z.ZodString;
5382
5395
  method: z.ZodString;
5383
5396
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
5397
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
5384
5398
  }, z.core.$strip>, z.ZodObject<{
5385
5399
  kind: z.ZodLiteral<"action">;
5386
5400
  actionId: z.ZodString;
@@ -5706,6 +5720,7 @@ export declare const coreBlocksCapability: {
5706
5720
  cap: z.ZodString;
5707
5721
  method: z.ZodString;
5708
5722
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
5723
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
5709
5724
  }, z.core.$strip>, z.ZodObject<{
5710
5725
  kind: z.ZodLiteral<"action">;
5711
5726
  actionId: z.ZodString;
@@ -6066,6 +6081,7 @@ export declare const coreBlocksCapability: {
6066
6081
  cap: z.ZodString;
6067
6082
  method: z.ZodString;
6068
6083
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
6084
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
6069
6085
  }, z.core.$strip>, z.ZodObject<{
6070
6086
  kind: z.ZodLiteral<"action">;
6071
6087
  actionId: z.ZodString;
@@ -6433,6 +6449,7 @@ export declare const coreBlocksCapability: {
6433
6449
  cap: z.ZodString;
6434
6450
  method: z.ZodString;
6435
6451
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
6452
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
6436
6453
  }, z.core.$strip>, z.ZodObject<{
6437
6454
  kind: z.ZodLiteral<"action">;
6438
6455
  actionId: z.ZodString;
@@ -124,6 +124,7 @@ export declare const remoteCapability: {
124
124
  cap: z.ZodString;
125
125
  method: z.ZodString;
126
126
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
127
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
127
128
  deviceId: z.ZodNumber;
128
129
  }, z.core.$strip>;
129
130
  }, z.core.$strip>>;
@@ -149,6 +150,7 @@ export declare const remoteCapability: {
149
150
  cap: z.ZodString;
150
151
  method: z.ZodString;
151
152
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
153
+ argUnits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
152
154
  deviceId: z.ZodNumber;
153
155
  }, z.core.$strip>;
154
156
  }, z.core.$strip>>;
@@ -20,6 +20,7 @@ import type * as CapRegistry from '../../generated/capability-router-map.js';
20
20
  import type { EventCategory } from '../../enums/event-category.js';
21
21
  import type { ICON_KEYS } from '../icon-catalog.generated.js';
22
22
  import type { DeviceRole, DeviceType } from '../device-type.js';
23
+ import type { ReadingQuantity } from '../../units/quantity.js';
23
24
  /** One catalog icon key (lucide id) — the same vocabulary as `IconKey`. */
24
25
  export type VocabIcon = (typeof ICON_KEYS)[number];
25
26
  /** A human string in every language the map carries. */
@@ -82,13 +83,20 @@ export interface EnumOffer {
82
83
  readonly kind: 'enum';
83
84
  readonly values: readonly VocabChoice[];
84
85
  }
85
- /** A number, within the Zod input's bounds. `unit` is a display suffix. */
86
+ /**
87
+ * A number, within the Zod input's bounds. With `quantity` the number is a
88
+ * physical quantity: `unit` is the unit the METHOD expects (what its input
89
+ * declares with `paramMeta`) and a client lets the person pick any unit of
90
+ * that quantity (`unitsForQuantity`), converting to `unit` before the call.
91
+ * Without `quantity`, `unit` is only a display suffix.
92
+ */
86
93
  export interface NumberOffer {
87
94
  readonly kind: 'number';
88
95
  readonly min?: number;
89
96
  readonly max?: number;
90
97
  readonly step?: number;
91
98
  readonly unit?: string;
99
+ readonly quantity?: ReadingQuantity;
92
100
  }
93
101
  /** Free text. */
94
102
  export interface TextOffer {
package/dist/index.d.ts CHANGED
@@ -163,8 +163,10 @@ export { APP_FLOW_DEFAULT_REDIRECT, APP_FLOW_REFUSAL_MESSAGES, APP_FLOW_STATE_PR
163
163
  export { SSO_STATE_COOKIE, SSO_STATE_COOKIE_MAX_AGE_SEC } from './auth/sso-state.js';
164
164
  export { buildDeviceEnrollmentLink, buildDeviceSignatureMessage, type CompleteEnrollmentInput, CompleteEnrollmentInputSchema, type CompleteEnrollmentOutput, CompleteEnrollmentOutputSchema, DEVICE_CERT_RENEW_WINDOW_DAYS, DEVICE_CERT_SIGNATURE, DEVICE_CERT_VALIDITY_DAYS, DEVICE_ENROLLMENT_TTL_MS, DEVICE_NONCE_TTL_MS, DEVICE_SAN_CREDENTIAL_PREFIX, DEVICE_SAN_USER_PREFIX, DEVICE_SIGNATURE_MESSAGE_VERSION, type DeviceCertificateLoginMethod, DeviceCertificateLoginMethodSchema, type DeviceChallenge, DeviceChallengeSchema, type DeviceCredential, DeviceCredentialSchema, type DeviceCredentialStatus, DeviceCredentialStatusSchema, type DevicePlatform, DevicePlatformSchema, type DeviceProofInput, DeviceProofInputSchema, type CompleteEnrollmentResult, CompleteEnrollmentResultSchema, DEFINITIVE_DEVICE_REFUSALS, DEVICE_DEFINITIVE_REFUSALS_BEFORE_DELETE, DEVICE_REFRESH_REFUSAL_PREFIX, deviceRefusalFromMessage, type DeviceChallengeResult, DeviceChallengeResultSchema, DeviceEnrollProofSchema, type DeviceRefusal, type DeviceRefusalReason, DeviceRefusalReasonSchema, DeviceRefusalSchema, type DeviceRevoker, type EnrollSelfInput, EnrollSelfInputSchema, formatDeviceRevoker, isDefinitiveDeviceRefusal, type RenewDeviceCertificateResult, RenewDeviceCertificateResultSchema, type RevokeOwnDeviceCertificateResult, RevokeOwnDeviceCertificateResultSchema, type DeviceSignaturePurpose, DeviceSignaturePurposeSchema, type RenewDeviceCertificateOutput, RenewDeviceCertificateOutputSchema, type StartEnrollmentOutput, StartEnrollmentOutputSchema, parseDeviceEnrollmentLink, } from './auth/device-certificate.js';
165
165
  export { advertisedHubOrigins, claimedRequestOrigins, normalizeOrigin, pickRequestOrigin, type RequestHeaders, requestMountPrefix, } from './auth/request-origin.js';
166
- export type { ActionStep, AutomationAction, AutomationCondition, AutomationConditionAll, AutomationConditionAny, AutomationConditionExpression, AutomationConditionLeaf, AutomationConditionStationaryPresent, AutomationConditionNot, AutomationConditionOperator, AutomationConditionTraceNode, AutomationRecipe, AutomationRunMode, AutomationRunOutcome, AutomationRunTrace, AutomationRunVerdict, AutomationStateDoc, AutomationStepTrace, AutomationTrigger, AutomationTriggerTrace, ConditionEvaluation, ConditionReader, DetectionDecision, DetectionTrigger, DetectionVars, GenerateAutomationBlockInput, MirrorRefreshFetchers, MirrorRefreshReport, MirrorSource, StationaryChangedInput, StationaryDecision, StationaryTrigger, StationaryVars, TraceNodeOutcome, TraceValue, TrackLifecycleInput, } from './automation/index.js';
166
+ export type { ActionStep, AutomationAction, AutomationCapStep, AutomationCondition, AutomationConditionAll, AutomationConditionAny, AutomationConditionExpression, AutomationConditionLeaf, AutomationConditionStationaryPresent, AutomationConditionNot, AutomationConditionOperator, AutomationConditionTraceNode, AutomationRecipe, AutomationRunMode, AutomationRunOutcome, AutomationRunTrace, AutomationRunVerdict, AutomationStateDoc, AutomationStepTrace, AutomationTrigger, AutomationTriggerTrace, ConditionEvaluation, ConditionReader, DetectionDecision, DetectionTrigger, DetectionVars, GenerateAutomationBlockInput, MirrorRefreshFetchers, MirrorRefreshReport, MirrorSource, StationaryChangedInput, StationaryDecision, StationaryTrigger, StationaryVars, TraceNodeOutcome, TraceValue, TrackLifecycleInput, } from './automation/index.js';
167
167
  export { ActionStepSchema, AutomationActionSchema, AutomationCapStepSchema, AutomationWaitStepSchema, EMPTY_AUTOMATION_STATE, mergeSkipTraces, AutomationConditionOperatorSchema, AutomationConditionSchema, AutomationConditionTraceNodeSchema, AutomationRecipeSchema, AutomationRunModeSchema, AutomationRunOutcomeSchema, AutomationRunTraceSchema, AutomationRunVerdictSchema, AutomationStateDocSchema, AutomationStepTraceSchema, AutomationTriggerSchema, AutomationTriggerTraceSchema, appendTrace, buildTriggerTrace, collectMirrorSources, ConditionMirror, conditionDepth, countConditionLeaves, DEFAULT_TRACE_KEEP, DetectionTriggerFilter, detectionClassMatches, evaluateConditionTree, evaluateStationaryTrigger, generateAutomationBlock, isSkippedTrace, MAX_CONDITION_DEPTH, MAX_CONDITION_LEAVES, MAX_TRACE_KEEP, RunGate, skipSignature, TraceNodeOutcomeSchema, TraceValueSchema, validateRecipeBounds, } from './automation/index.js';
168
+ export { UnitWarningSchema, capUnitResolver, normalizeActionUnits, normalizeConditionUnits, normalizeRecipeUnits, } from './automation/index.js';
169
+ export type { UnitResolver, UnitWarning, UnitsNormalized } from './automation/index.js';
168
170
  export * from './automation/action.js';
169
171
  export * from './automation/step-runner.js';
170
172
  export * from './automation/export-entities.js';