@camstack/types 1.2.417 → 1.2.419
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/dist/addon.js +2 -2
- package/dist/addon.mjs +2 -2
- package/dist/capabilities/addons.cap.d.ts +67 -1
- package/dist/capabilities/capability-definition.d.ts +5 -0
- package/dist/capabilities/color.cap.d.ts +1 -0
- package/dist/capabilities/composer.cap.d.ts +201 -0
- package/dist/capabilities/core-blocks.cap.d.ts +1441 -0
- package/dist/capabilities/group-commands.cap.d.ts +49 -0
- package/dist/capabilities/group-status.cap.d.ts +46 -0
- package/dist/capabilities/index.d.ts +6 -2
- package/dist/capabilities/motion.cap.d.ts +12 -4
- package/dist/capabilities/notification-rules.cap.d.ts +46 -0
- package/dist/capabilities/osd-manager.cap.d.ts +12 -0
- package/dist/client.js +37 -5
- package/dist/client.mjs +37 -5
- package/dist/composition/composition-report.d.ts +72 -0
- package/dist/composition/composition.d.ts +286 -5
- package/dist/composition/helpers/actuator.d.ts +58 -0
- package/dist/composition/helpers/aggregate.d.ts +41 -0
- package/dist/composition/helpers/catalog.d.ts +47 -0
- package/dist/composition/helpers/compile.d.ts +22 -0
- package/dist/composition/helpers/index.d.ts +7 -0
- package/dist/composition/helpers/save.d.ts +18 -0
- package/dist/composition/helpers/source-pick.d.ts +40 -0
- package/dist/composition/helpers/spec.d.ts +43 -0
- package/dist/composition/index.d.ts +1 -0
- package/dist/composition/source-ref.d.ts +11 -0
- package/dist/composition/validate-composition.d.ts +5 -0
- package/dist/{composition-kEl9mevu.mjs → composition-OhpuespA.mjs} +121 -8
- package/dist/{composition-DsmkwP9-.js → composition-re1aezX9.js} +198 -7
- package/dist/device/cap-vocabulary/entries/sensors.d.ts +1 -1
- package/dist/enums/event-category.d.ts +8 -0
- package/dist/enums.js +1 -1
- package/dist/enums.mjs +1 -1
- package/dist/{event-category-DXZ3f9Q5.js → event-category-Ave2VSxY.js} +8 -0
- package/dist/{event-category-DHXxB8t9.mjs → event-category-CT-hz5Rb.mjs} +8 -0
- package/dist/generated/addon-api.d.ts +35 -0
- package/dist/generated/addon-cap-facts.d.ts +1 -1
- package/dist/generated/cap-status-types.d.ts +5 -1
- package/dist/generated/capability-router-map.d.ts +8 -2
- package/dist/generated/device-local-state.d.ts +6 -0
- package/dist/generated/device-proxy.d.ts +6 -0
- package/dist/generated/device-scoped-caps.d.ts +1 -1
- package/dist/generated/history-catalog.d.ts +1 -1
- package/dist/generated/method-access-map.d.ts +1 -1
- package/dist/generated/method-device-selectors.d.ts +1 -1
- package/dist/generated/runtime-state-durability.d.ts +1 -1
- package/dist/generated/system-proxy.d.ts +1 -1
- package/dist/index.js +1040 -24
- package/dist/index.mjs +1006 -25
- package/dist/interfaces/event-bus.d.ts +15 -0
- package/dist/node.js +1 -1
- package/dist/node.mjs +1 -1
- package/dist/{sleep-gtskVoMw.js → sleep-YJ6FVsUu.js} +26 -2
- package/dist/{sleep-CARd6wZF.mjs → sleep-bykKrTgu.mjs} +26 -2
- package/package.json +1 -1
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Actuator groups (D944 phase 1b). The active boolean is the binary reducer
|
|
3
|
+
* with unknown members left out. A command is one call per member that binds
|
|
4
|
+
* the cap, including members that are offline. One failure does not cancel
|
|
5
|
+
* the others.
|
|
6
|
+
*/
|
|
7
|
+
import { DeviceFeature } from '../../device/device-type.js';
|
|
8
|
+
import type { ActiveCriterion, BinaryAggregate } from './spec.js';
|
|
9
|
+
/** Caps a light group may expose, in display order. Switch is the active state. */
|
|
10
|
+
export declare const LIGHT_SHARED_CAPS: readonly ['switch', 'brightness', 'color'];
|
|
11
|
+
export type LightSharedCap = (typeof LIGHT_SHARED_CAPS)[number];
|
|
12
|
+
/** How many member calls run at once. The rest wait; none are dropped. */
|
|
13
|
+
export declare const FAN_OUT_CONCURRENCY: number;
|
|
14
|
+
export interface FanOutMember {
|
|
15
|
+
readonly deviceId: number;
|
|
16
|
+
readonly caps: readonly string[];
|
|
17
|
+
/** Offline members are still commanded — they may wake. Not a reason to skip. */
|
|
18
|
+
readonly online: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface FanOutCall {
|
|
21
|
+
readonly deviceId: number;
|
|
22
|
+
readonly cap: string;
|
|
23
|
+
readonly method: string;
|
|
24
|
+
readonly args: Readonly<Record<string, unknown>>;
|
|
25
|
+
}
|
|
26
|
+
export interface FanOutOk {
|
|
27
|
+
readonly deviceId: number;
|
|
28
|
+
readonly ok: true;
|
|
29
|
+
}
|
|
30
|
+
export interface FanOutFailed {
|
|
31
|
+
readonly deviceId: number;
|
|
32
|
+
readonly ok: false;
|
|
33
|
+
readonly error: string;
|
|
34
|
+
}
|
|
35
|
+
export type FanOutMemberResult = FanOutOk | FanOutFailed;
|
|
36
|
+
/** `at-least-one` is any included member on; `all` is every included member on. */
|
|
37
|
+
export declare function reducerForActive(active: ActiveCriterion): BinaryAggregate;
|
|
38
|
+
export declare function activeForReducer(reducer: BinaryAggregate): ActiveCriterion;
|
|
39
|
+
/**
|
|
40
|
+
* Caps every member binds, from {@link LIGHT_SHARED_CAPS}. An empty member
|
|
41
|
+
* list shares nothing. A member that lacks colour drops colour from the group.
|
|
42
|
+
*/
|
|
43
|
+
export declare function sharedLightCaps(memberCaps: readonly (readonly string[])[]): readonly string[];
|
|
44
|
+
/**
|
|
45
|
+
* Colour modes every member advertises. Offline does not remove a mode:
|
|
46
|
+
* the caller passes device features, not liveness. No members → no mode.
|
|
47
|
+
*/
|
|
48
|
+
export declare function sharedColorModes(memberFeatures: readonly (readonly string[])[]): readonly DeviceFeature[];
|
|
49
|
+
/**
|
|
50
|
+
* One call per member that binds `cap`. Offline members stay in the list.
|
|
51
|
+
* A member without the cap is not called — the command cannot reach it.
|
|
52
|
+
*/
|
|
53
|
+
export declare function fanOutTargets(members: readonly FanOutMember[], cap: string, method: string, args: Readonly<Record<string, unknown>>): readonly FanOutCall[];
|
|
54
|
+
/**
|
|
55
|
+
* Run every call. A throw is that member's result; the other calls still run.
|
|
56
|
+
* At most {@link FAN_OUT_CONCURRENCY} are in flight.
|
|
57
|
+
*/
|
|
58
|
+
export declare function runFanOut(calls: readonly FanOutCall[], invoke: (call: FanOutCall) => Promise<void>): Promise<readonly FanOutMemberResult[]>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A group reducer (D944). Offline and unknown members are excluded and
|
|
3
|
+
* counted. They are never passed in as 0 or false (D393). A free expression
|
|
4
|
+
* does not use this — `avg` / `any` still include a stale value.
|
|
5
|
+
*/
|
|
6
|
+
import type { ExpressionValue } from '../../expression/ast.js';
|
|
7
|
+
import type { AggregateReducer } from './spec.js';
|
|
8
|
+
export interface AggregateReadResult {
|
|
9
|
+
readonly state: 'fresh' | 'stale' | 'unavailable';
|
|
10
|
+
readonly value?: ExpressionValue;
|
|
11
|
+
/** Set when `state` is `unavailable` and the source is gone. */
|
|
12
|
+
readonly fatal?: boolean;
|
|
13
|
+
readonly reason?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface AggregateCounts {
|
|
16
|
+
readonly included: number;
|
|
17
|
+
readonly excluded: number;
|
|
18
|
+
readonly total: number;
|
|
19
|
+
}
|
|
20
|
+
export type AggregatePublish = 'value' | 'included' | 'excluded' | 'total';
|
|
21
|
+
export type AggregateEmpty = 'null' | 'omit' | 'offline';
|
|
22
|
+
export interface EvaluateAggregateInput {
|
|
23
|
+
readonly reducer: AggregateReducer;
|
|
24
|
+
readonly members: readonly AggregateReadResult[];
|
|
25
|
+
readonly publish: AggregatePublish;
|
|
26
|
+
readonly empty: AggregateEmpty;
|
|
27
|
+
}
|
|
28
|
+
export interface AggregateValue {
|
|
29
|
+
readonly kind: 'value';
|
|
30
|
+
readonly value: number | boolean | null;
|
|
31
|
+
readonly counts: AggregateCounts;
|
|
32
|
+
}
|
|
33
|
+
export interface AggregateUnavailable {
|
|
34
|
+
readonly kind: 'unavailable';
|
|
35
|
+
readonly fatal: boolean;
|
|
36
|
+
readonly reason: string;
|
|
37
|
+
readonly counts: AggregateCounts;
|
|
38
|
+
}
|
|
39
|
+
export type AggregateOutcome = AggregateValue | AggregateUnavailable;
|
|
40
|
+
/** Pure. `members` is not mutated. An empty included set is null or unavailable, never 0 or false. */
|
|
41
|
+
export declare function evaluateAggregate(input: EvaluateAggregateInput): AggregateOutcome;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One catalog row per base reading a group helper can build (D944 §3).
|
|
3
|
+
* Data, not a form default written into the block.
|
|
4
|
+
*/
|
|
5
|
+
import { DeviceRole, DeviceType } from '../../device/device-type.js';
|
|
6
|
+
import { type ReadingQuantity } from '../../units/quantity.js';
|
|
7
|
+
import type { AggregateEmpty } from './aggregate.js';
|
|
8
|
+
import { type AggregateReducer, type GroupTemplateId } from './spec.js';
|
|
9
|
+
export interface HelperAccept {
|
|
10
|
+
readonly cap: string;
|
|
11
|
+
readonly fieldPath: string;
|
|
12
|
+
}
|
|
13
|
+
export interface HelperCompanion {
|
|
14
|
+
readonly fieldPath: string;
|
|
15
|
+
readonly expr: string;
|
|
16
|
+
}
|
|
17
|
+
export interface GroupTemplate {
|
|
18
|
+
readonly id: GroupTemplateId;
|
|
19
|
+
readonly family: 'numeric' | 'binary' | 'actuator';
|
|
20
|
+
readonly summary: string;
|
|
21
|
+
readonly deviceType: DeviceType;
|
|
22
|
+
readonly role: DeviceRole | undefined;
|
|
23
|
+
/** Members are this one device type. */
|
|
24
|
+
readonly memberDeviceType: DeviceType;
|
|
25
|
+
readonly outputCap: string;
|
|
26
|
+
readonly outputField: string;
|
|
27
|
+
/**
|
|
28
|
+
* Methods the composer fans out. Empty for a reading. A free composition
|
|
29
|
+
* still cannot serve these caps (`has-commands`).
|
|
30
|
+
*/
|
|
31
|
+
readonly commandCaps: readonly string[];
|
|
32
|
+
/** Quantity of the output reading. `device` is chosen per numeric sensor. */
|
|
33
|
+
readonly quantity: ReadingQuantity;
|
|
34
|
+
readonly baseUnit: string | undefined;
|
|
35
|
+
readonly aggregates: readonly AggregateReducer[];
|
|
36
|
+
readonly defaultAggregate: AggregateReducer;
|
|
37
|
+
/**
|
|
38
|
+
* No included member: `null` writes null and stays online; `omit` leaves an
|
|
39
|
+
* optional key out and stays online; `offline` takes the device offline
|
|
40
|
+
* rather than publishing false (D393).
|
|
41
|
+
*/
|
|
42
|
+
readonly empty: AggregateEmpty;
|
|
43
|
+
readonly accept: readonly HelperAccept[];
|
|
44
|
+
readonly companions: readonly HelperCompanion[];
|
|
45
|
+
}
|
|
46
|
+
export declare const GROUP_TEMPLATES: readonly GroupTemplate[];
|
|
47
|
+
export declare function groupTemplate(id: GroupTemplateId): GroupTemplate | null;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project a helper spec onto the composition the composer already runs (D944).
|
|
3
|
+
* Pure: it stores nothing. A group does not compile to `avg(...)` / `any(...)`.
|
|
4
|
+
*/
|
|
5
|
+
import { DeviceType } from '../../device/device-type.js';
|
|
6
|
+
import { type Composition } from '../composition.js';
|
|
7
|
+
import type { CompositionProblem } from '../composition-report.js';
|
|
8
|
+
import { type HelperSpec } from './spec.js';
|
|
9
|
+
export interface HelperCompiled {
|
|
10
|
+
readonly ok: true;
|
|
11
|
+
readonly composition: Composition;
|
|
12
|
+
}
|
|
13
|
+
export interface HelperRefused {
|
|
14
|
+
readonly ok: false;
|
|
15
|
+
readonly problems: readonly CompositionProblem[];
|
|
16
|
+
}
|
|
17
|
+
export type HelperCompileResult = HelperCompiled | HelperRefused;
|
|
18
|
+
/** Compile a group template to a new-device composition. Refusals are named. */
|
|
19
|
+
export declare function compileHelper(spec: HelperSpec): HelperCompileResult;
|
|
20
|
+
/** The built body, ignoring `helper`, so a save can demand one writer. */
|
|
21
|
+
export declare function sameHelperBody(stored: Composition, compiled: Composition): boolean;
|
|
22
|
+
export declare function templateDeviceType(spec: HelperSpec): DeviceType | null;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { FAN_OUT_CONCURRENCY, LIGHT_SHARED_CAPS, type FanOutCall, type FanOutFailed, type FanOutMember, type FanOutMemberResult, type FanOutOk, type LightSharedCap, activeForReducer, fanOutTargets, reducerForActive, runFanOut, sharedColorModes, sharedLightCaps, } from './actuator.js';
|
|
2
|
+
export { type AggregateCounts, type AggregateEmpty, type AggregateOutcome, type AggregatePublish, type AggregateReadResult, type AggregateUnavailable, type AggregateValue, type EvaluateAggregateInput, evaluateAggregate, } from './aggregate.js';
|
|
3
|
+
export { type GroupTemplate, type HelperAccept, type HelperCompanion, GROUP_TEMPLATES, groupTemplate, } from './catalog.js';
|
|
4
|
+
export { type HelperCompileResult, type HelperCompiled, type HelperRefused, compileHelper, sameHelperBody, templateDeviceType, } from './compile.js';
|
|
5
|
+
export { type HelperMemberFact, helperSaveProblems, } from './save.js';
|
|
6
|
+
export { type SourcePick, type SourcePickAccept, type SourcePickHistory, type SourcePickRequest, sourcePickForTemplate, } from './source-pick.js';
|
|
7
|
+
export { ACTIVE_CRITERIA, AGGREGATE_REDUCERS, ActiveCriterionSchema, AggregateReducerSchema, BINARY_AGGREGATES, GROUP_TEMPLATE_IDS, GroupHelperSpecSchema, GroupTemplateIdSchema, HelperMemberSchema, HelperSpecSchema, MAX_HELPER_MEMBERS, NUMERIC_AGGREGATES, type ActiveCriterion, type AggregateReducer, type BinaryAggregate, type GroupHelperSpec, type GroupTemplateId, type HelperMember, type HelperSpec, type NumericAggregate, } from './spec.js';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Save-time checks a pure compile cannot make: the compiled features must be
|
|
3
|
+
* this spec's, and members that report a quantity must share one (D944 §4).
|
|
4
|
+
*/
|
|
5
|
+
import type { DeviceType } from '../../device/device-type.js';
|
|
6
|
+
import type { ReadingQuantity } from '../../units/quantity.js';
|
|
7
|
+
import { type Composition } from '../composition.js';
|
|
8
|
+
import type { CompositionProblem } from '../composition-report.js';
|
|
9
|
+
/** What a save learned about one member device. Absent keys were not read. */
|
|
10
|
+
export interface HelperMemberFact {
|
|
11
|
+
readonly deviceType?: DeviceType;
|
|
12
|
+
readonly quantity?: ReadingQuantity;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Problems that refuse a save. No `helper` key means a free composition: this
|
|
16
|
+
* returns nothing, and expression semantics stay as they are.
|
|
17
|
+
*/
|
|
18
|
+
export declare function helperSaveProblems(composition: Composition, facts: ReadonlyMap<string, HelperMemberFact>): readonly CompositionProblem[];
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The request the common source selector (#236) accepts for a helper (D944 §5).
|
|
3
|
+
* The selector's layout is not specified here. Groups ask for one device type
|
|
4
|
+
* and the catalog field; they do not opt into incompatible fields.
|
|
5
|
+
*/
|
|
6
|
+
import type { DeviceType } from '../../device/device-type.js';
|
|
7
|
+
import type { CompositionSourceRef } from '../source-ref.js';
|
|
8
|
+
import type { GroupTemplate } from './catalog.js';
|
|
9
|
+
export interface SourcePickAccept {
|
|
10
|
+
readonly cap: string;
|
|
11
|
+
readonly fieldPath: string;
|
|
12
|
+
readonly valueKind: 'number' | 'boolean';
|
|
13
|
+
}
|
|
14
|
+
export interface SourcePickHistory {
|
|
15
|
+
readonly required: boolean;
|
|
16
|
+
readonly minRetentionMs: number | null;
|
|
17
|
+
}
|
|
18
|
+
export interface SourcePickRequest {
|
|
19
|
+
readonly purpose: 'member' | 'reading' | 'historised';
|
|
20
|
+
readonly multiple: boolean;
|
|
21
|
+
readonly max: number;
|
|
22
|
+
readonly deviceTypes: readonly DeviceType[];
|
|
23
|
+
readonly accept: readonly SourcePickAccept[];
|
|
24
|
+
readonly history: SourcePickHistory;
|
|
25
|
+
readonly mustBindCaps: readonly string[];
|
|
26
|
+
readonly exclude: readonly CompositionSourceRef[];
|
|
27
|
+
}
|
|
28
|
+
export interface SourcePick {
|
|
29
|
+
readonly source: CompositionSourceRef;
|
|
30
|
+
readonly deviceId: number;
|
|
31
|
+
readonly parentName: string | null;
|
|
32
|
+
readonly cap: string;
|
|
33
|
+
readonly fieldPath: string;
|
|
34
|
+
/** Current reading. `null` is unknown, never a stand-in 0. */
|
|
35
|
+
readonly current: number | boolean | string | null;
|
|
36
|
+
readonly compatibility: 'direct' | 'convert' | 'incompatible';
|
|
37
|
+
readonly history: 'recorded' | 'absent' | 'unknown';
|
|
38
|
+
}
|
|
39
|
+
/** What the member step asks the selector for this template. */
|
|
40
|
+
export declare function sourcePickForTemplate(template: GroupTemplate): SourcePickRequest;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A helper spec is what the editor stores and reads back (D944). The compiled
|
|
3
|
+
* features are a projection; the editor never edits the expression.
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { CompositionSourceRefSchema } from '../source-ref.js';
|
|
7
|
+
/** A group may name more members than an expression call (the 16-arg cap). */
|
|
8
|
+
export declare const MAX_HELPER_MEMBERS: number;
|
|
9
|
+
export declare const GROUP_TEMPLATE_IDS: readonly ['temperature', 'humidity', 'pressure', 'illuminance', 'power', 'energy', 'battery', 'numeric', 'motion', 'contact', 'leak', 'smoke', 'occupancy', 'binary', 'switch', 'light'];
|
|
10
|
+
export type GroupTemplateId = (typeof GROUP_TEMPLATE_IDS)[number];
|
|
11
|
+
export declare const NUMERIC_AGGREGATES: readonly ['mean', 'median', 'min', 'max', 'sum'];
|
|
12
|
+
export type NumericAggregate = (typeof NUMERIC_AGGREGATES)[number];
|
|
13
|
+
export declare const BINARY_AGGREGATES: readonly ['any', 'all'];
|
|
14
|
+
export type BinaryAggregate = (typeof BINARY_AGGREGATES)[number];
|
|
15
|
+
/** How an actuator group decides it is on. Unknown members never count as off. */
|
|
16
|
+
export declare const ACTIVE_CRITERIA: readonly ['at-least-one', 'all'];
|
|
17
|
+
export type ActiveCriterion = (typeof ACTIVE_CRITERIA)[number];
|
|
18
|
+
export declare const AGGREGATE_REDUCERS: readonly ['mean', 'median', 'min', 'max', 'sum', 'any', 'all'];
|
|
19
|
+
export type AggregateReducer = (typeof AGGREGATE_REDUCERS)[number];
|
|
20
|
+
export declare const GroupTemplateIdSchema: z.ZodType<GroupTemplateId>;
|
|
21
|
+
export declare const AggregateReducerSchema: z.ZodType<AggregateReducer>;
|
|
22
|
+
export declare const ActiveCriterionSchema: z.ZodType<ActiveCriterion>;
|
|
23
|
+
/** One member. The field is stored so occupancy can name motion or binary. */
|
|
24
|
+
export declare const HelperMemberSchema: z.ZodObject<{
|
|
25
|
+
source: typeof CompositionSourceRefSchema;
|
|
26
|
+
cap: z.ZodString;
|
|
27
|
+
fieldPath: z.ZodString;
|
|
28
|
+
}>;
|
|
29
|
+
export type HelperMember = z.infer<typeof HelperMemberSchema>;
|
|
30
|
+
/**
|
|
31
|
+
* Phase 1a is groups only. Math, integral and statistics stay off this union
|
|
32
|
+
* until the composer can run them — a control must not save a spec it cannot.
|
|
33
|
+
*/
|
|
34
|
+
export declare const GroupHelperSpecSchema: z.ZodObject<{
|
|
35
|
+
kind: z.ZodLiteral<'group'>;
|
|
36
|
+
templateId: typeof GroupTemplateIdSchema;
|
|
37
|
+
aggregate: typeof AggregateReducerSchema;
|
|
38
|
+
members: z.ZodArray<typeof HelperMemberSchema>;
|
|
39
|
+
active: z.ZodOptional<typeof ActiveCriterionSchema>;
|
|
40
|
+
}>;
|
|
41
|
+
export type GroupHelperSpec = z.infer<typeof GroupHelperSpecSchema>;
|
|
42
|
+
export declare const HelperSpecSchema: z.ZodDiscriminatedUnion<[typeof GroupHelperSpecSchema], 'kind'>;
|
|
43
|
+
export type HelperSpec = z.infer<typeof HelperSpecSchema>;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* inside @camstack/types import the deep modules, never this file.
|
|
4
4
|
*/
|
|
5
5
|
export * from './composable-caps.js';
|
|
6
|
+
export * from './helpers/index.js';
|
|
6
7
|
export * from './composition.js';
|
|
7
8
|
export * from './composition-events.js';
|
|
8
9
|
export * from './composition-graph.js';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
3
|
+
* id. Split out so helper schemas can name it without a cycle through
|
|
4
|
+
* `composition.ts` (D659).
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
export declare const CompositionSourceRefSchema: z.ZodObject<{
|
|
8
|
+
addonId: z.ZodString;
|
|
9
|
+
stableId: z.ZodString;
|
|
10
|
+
}>;
|
|
11
|
+
export type CompositionSourceRef = z.infer<typeof CompositionSourceRefSchema>;
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import type { CapabilityDefinition } from '../capabilities/capability-definition.js';
|
|
12
12
|
import type { DeviceType } from '../device/device-type.js';
|
|
13
|
+
import type { ReadingQuantity } from '../units/quantity.js';
|
|
13
14
|
import { type Composition, type CompositionSourceRef } from './composition.js';
|
|
14
15
|
import { type CompositionPlanResult } from './plan-result.js';
|
|
15
16
|
import { type CompositionPeer } from './composition-graph.js';
|
|
@@ -22,6 +23,10 @@ export interface CompositionSourceFound {
|
|
|
22
23
|
readonly kind: 'found';
|
|
23
24
|
readonly deviceId: number;
|
|
24
25
|
readonly caps: ReadonlySet<string>;
|
|
26
|
+
/** Present when the row was read. A helper group requires this one type. */
|
|
27
|
+
readonly deviceType?: DeviceType;
|
|
28
|
+
/** Present when the device declares one. Mixed quantities are refused. */
|
|
29
|
+
readonly quantity?: ReadingQuantity;
|
|
25
30
|
}
|
|
26
31
|
export interface CompositionSourceAbsent {
|
|
27
32
|
readonly kind: 'absent';
|
|
@@ -2160,6 +2160,85 @@ function evaluateExpressionSource(expr, bindingValues, now, opts) {
|
|
|
2160
2160
|
}
|
|
2161
2161
|
}
|
|
2162
2162
|
//#endregion
|
|
2163
|
+
//#region src/composition/source-ref.ts
|
|
2164
|
+
/**
|
|
2165
|
+
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
2166
|
+
* id. Split out so helper schemas can name it without a cycle through
|
|
2167
|
+
* `composition.ts` (D659).
|
|
2168
|
+
*/
|
|
2169
|
+
var CompositionSourceRefSchema = z.object({
|
|
2170
|
+
/** The owning addon; `stableId` is unique only within it. */
|
|
2171
|
+
addonId: z.string().min(1),
|
|
2172
|
+
stableId: z.string().min(1)
|
|
2173
|
+
});
|
|
2174
|
+
//#endregion
|
|
2175
|
+
//#region src/composition/helpers/spec.ts
|
|
2176
|
+
/**
|
|
2177
|
+
* A helper spec is what the editor stores and reads back (D944). The compiled
|
|
2178
|
+
* features are a projection; the editor never edits the expression.
|
|
2179
|
+
*/
|
|
2180
|
+
/** A group may name more members than an expression call (the 16-arg cap). */
|
|
2181
|
+
var MAX_HELPER_MEMBERS = 64;
|
|
2182
|
+
var GROUP_TEMPLATE_IDS = [
|
|
2183
|
+
"temperature",
|
|
2184
|
+
"humidity",
|
|
2185
|
+
"pressure",
|
|
2186
|
+
"illuminance",
|
|
2187
|
+
"power",
|
|
2188
|
+
"energy",
|
|
2189
|
+
"battery",
|
|
2190
|
+
"numeric",
|
|
2191
|
+
"motion",
|
|
2192
|
+
"contact",
|
|
2193
|
+
"leak",
|
|
2194
|
+
"smoke",
|
|
2195
|
+
"occupancy",
|
|
2196
|
+
"binary",
|
|
2197
|
+
"switch",
|
|
2198
|
+
"light"
|
|
2199
|
+
];
|
|
2200
|
+
var NUMERIC_AGGREGATES = [
|
|
2201
|
+
"mean",
|
|
2202
|
+
"median",
|
|
2203
|
+
"min",
|
|
2204
|
+
"max",
|
|
2205
|
+
"sum"
|
|
2206
|
+
];
|
|
2207
|
+
var BINARY_AGGREGATES = ["any", "all"];
|
|
2208
|
+
/** How an actuator group decides it is on. Unknown members never count as off. */
|
|
2209
|
+
var ACTIVE_CRITERIA = ["at-least-one", "all"];
|
|
2210
|
+
var AGGREGATE_REDUCERS = [
|
|
2211
|
+
"mean",
|
|
2212
|
+
"median",
|
|
2213
|
+
"min",
|
|
2214
|
+
"max",
|
|
2215
|
+
"sum",
|
|
2216
|
+
"any",
|
|
2217
|
+
"all"
|
|
2218
|
+
];
|
|
2219
|
+
var GroupTemplateIdSchema = z.enum(GROUP_TEMPLATE_IDS);
|
|
2220
|
+
var AggregateReducerSchema = z.enum(AGGREGATE_REDUCERS);
|
|
2221
|
+
var ActiveCriterionSchema = z.enum(ACTIVE_CRITERIA);
|
|
2222
|
+
/** One member. The field is stored so occupancy can name motion or binary. */
|
|
2223
|
+
var HelperMemberSchema = z.object({
|
|
2224
|
+
source: CompositionSourceRefSchema,
|
|
2225
|
+
cap: z.string().min(1),
|
|
2226
|
+
fieldPath: z.string().min(1)
|
|
2227
|
+
});
|
|
2228
|
+
/**
|
|
2229
|
+
* Phase 1a is groups only. Math, integral and statistics stay off this union
|
|
2230
|
+
* until the composer can run them — a control must not save a spec it cannot.
|
|
2231
|
+
*/
|
|
2232
|
+
var GroupHelperSpecSchema = z.object({
|
|
2233
|
+
kind: z.literal("group"),
|
|
2234
|
+
templateId: GroupTemplateIdSchema,
|
|
2235
|
+
aggregate: AggregateReducerSchema,
|
|
2236
|
+
members: z.array(HelperMemberSchema).min(1).max(64),
|
|
2237
|
+
/** Actuator groups only. Readings leave this unset. */
|
|
2238
|
+
active: ActiveCriterionSchema.optional()
|
|
2239
|
+
});
|
|
2240
|
+
var HelperSpecSchema = z.discriminatedUnion("kind", [GroupHelperSpecSchema]);
|
|
2241
|
+
//#endregion
|
|
2163
2242
|
//#region src/composition/composition.ts
|
|
2164
2243
|
/**
|
|
2165
2244
|
* A COMPOSITION: a device assembled from other devices' state (D659).
|
|
@@ -2195,11 +2274,6 @@ var MAX_COMPOSITION_FEATURES = 16;
|
|
|
2195
2274
|
var MAX_COMPOSITION_FIELDS_PER_FEATURE = 32;
|
|
2196
2275
|
/** Longest snippet a `code` source may carry (slice 4). */
|
|
2197
2276
|
var MAX_COMPOSITION_CODE_LENGTH = 2e4;
|
|
2198
|
-
var CompositionSourceRefSchema = z.object({
|
|
2199
|
-
/** The owning addon; `stableId` is unique only within it. */
|
|
2200
|
-
addonId: z.string().min(1),
|
|
2201
|
-
stableId: z.string().min(1)
|
|
2202
|
-
});
|
|
2203
2277
|
/** One field of one capability of one source device. */
|
|
2204
2278
|
var CompositionFieldReadSchema = z.object({
|
|
2205
2279
|
source: CompositionSourceRefSchema,
|
|
@@ -2242,10 +2316,42 @@ var CompositionCodeSourceSchema = z.object({
|
|
|
2242
2316
|
kind: z.literal("code"),
|
|
2243
2317
|
code: z.string().min(1).max(MAX_COMPOSITION_CODE_LENGTH)
|
|
2244
2318
|
});
|
|
2319
|
+
/**
|
|
2320
|
+
* `aggregate`: a group reducer. Offline and unknown reads are excluded, not
|
|
2321
|
+
* folded in as 0 or false (D944). Free expressions stay `expression` so a
|
|
2322
|
+
* stale member is still included there.
|
|
2323
|
+
*/
|
|
2324
|
+
var CompositionAggregateSourceSchema = z.object({
|
|
2325
|
+
kind: z.literal("aggregate"),
|
|
2326
|
+
reducer: z.enum([
|
|
2327
|
+
"mean",
|
|
2328
|
+
"median",
|
|
2329
|
+
"min",
|
|
2330
|
+
"max",
|
|
2331
|
+
"sum",
|
|
2332
|
+
"any",
|
|
2333
|
+
"all"
|
|
2334
|
+
]),
|
|
2335
|
+
reads: z.array(CompositionFieldReadSchema).min(1).max(64),
|
|
2336
|
+
/** `value` is the reading; the others are the member counts. */
|
|
2337
|
+
publish: z.enum([
|
|
2338
|
+
"value",
|
|
2339
|
+
"included",
|
|
2340
|
+
"excluded",
|
|
2341
|
+
"total"
|
|
2342
|
+
]),
|
|
2343
|
+
/** What a `value` publish does when nobody is included. Counts ignore this. */
|
|
2344
|
+
empty: z.enum([
|
|
2345
|
+
"null",
|
|
2346
|
+
"omit",
|
|
2347
|
+
"offline"
|
|
2348
|
+
])
|
|
2349
|
+
});
|
|
2245
2350
|
var CompositionFieldSourceSchema = z.discriminatedUnion("kind", [
|
|
2246
2351
|
CompositionFromSourceSchema,
|
|
2247
2352
|
CompositionExpressionSourceSchema,
|
|
2248
|
-
CompositionCodeSourceSchema
|
|
2353
|
+
CompositionCodeSourceSchema,
|
|
2354
|
+
CompositionAggregateSourceSchema
|
|
2249
2355
|
]);
|
|
2250
2356
|
/** `forward`: RESERVED for slice 3. Argument mapping arrives there as an additive optional `args`. */
|
|
2251
2357
|
var CompositionForwardCommandSchema = z.object({
|
|
@@ -2311,7 +2417,13 @@ var CompositionExistingTargetSchema = z.object({
|
|
|
2311
2417
|
var CompositionTargetSchema = z.discriminatedUnion("kind", [CompositionNewTargetSchema, CompositionExistingTargetSchema]);
|
|
2312
2418
|
var CompositionSchema = z.object({
|
|
2313
2419
|
target: CompositionTargetSchema,
|
|
2314
|
-
features: z.array(CompositionFeatureSchema).min(1).max(16)
|
|
2420
|
+
features: z.array(CompositionFeatureSchema).min(1).max(16),
|
|
2421
|
+
/**
|
|
2422
|
+
* Present when the block is a helper template. Absent on a free
|
|
2423
|
+
* composition (the room example, device 4603). The editor reads this,
|
|
2424
|
+
* never the compiled features.
|
|
2425
|
+
*/
|
|
2426
|
+
helper: HelperSpecSchema.optional()
|
|
2315
2427
|
}).superRefine((composition, ctx) => {
|
|
2316
2428
|
const seen = /* @__PURE__ */ new Set();
|
|
2317
2429
|
composition.features.forEach((feature, index) => {
|
|
@@ -2358,6 +2470,7 @@ function fieldReads(source) {
|
|
|
2358
2470
|
cap: binding.cap,
|
|
2359
2471
|
fieldPath: binding.fieldPath
|
|
2360
2472
|
}] : []);
|
|
2473
|
+
case "aggregate": return source.reads;
|
|
2361
2474
|
case "code": return [];
|
|
2362
2475
|
}
|
|
2363
2476
|
}
|
|
@@ -2384,4 +2497,4 @@ function featureSources(feature) {
|
|
|
2384
2497
|
return featureFieldEntries(feature).map((e) => e.source);
|
|
2385
2498
|
}
|
|
2386
2499
|
//#endregion
|
|
2387
|
-
export {
|
|
2500
|
+
export { createStatefulExpressionMemory as $, pickVideoEncoder as $t, compositionFeatureEnabled as A, SOURCE_DEVICE_TYPES as At, ActiveCriterionSchema as B, getFfmpegArtifact as Bt, CompositionTargetSchema as C, isStatefulBuiltin as Ct, MAX_COMPOSITION_ITEMS as D, SOURCE_CAPS as Dt, MAX_COMPOSITION_FIELDS_PER_FEATURE as E, DEFAULT_FIRST_SIGHTING_FRESHNESS_MS as Et, featureFieldEntries as F, sliceChangedAt as Ft, GroupTemplateIdSchema as G, audioPlanFromEncodeProfile as Gt, BINARY_AGGREGATES as H, canonicalHash as Ht, featureSources as I, FFMPEG_PATH_ENV as It, MAX_HELPER_MEMBERS as J, buildInputArgs as Jt, HelperMemberSchema as K, buildAudioArgs as Kt, fieldReads as L, chooseFfmpegBinary as Lt, compositionReadKey as M, evaluateSensorLevelEdge as Mt, compositionSliceKey as N, isSourceCap as Nt, composedDeviceRef as O, SOURCE_CAP_ACTIVE_FIELD as Ot, compositionSourceKey as P, sliceActiveValue as Pt, cloneStatefulExpressionMemory as Q, logBannerArgs as Qt, ACTIVE_CRITERIA as R, ffmpegBinaryName as Rt, CompositionSchema as S, evaluateRose as St, MAX_COMPOSITION_FEATURES as T, ExpressionParseError as Tt, GROUP_TEMPLATE_IDS as U, Fmp4BoxSplitter as Ut, AggregateReducerSchema as V, getFfmpegDownloadUrl as Vt, GroupHelperSpecSchema as W, AUDIO_PRESETS as Wt, CompositionSourceRefSchema as X, invocationFromEncodeProfile as Xt, NUMERIC_AGGREGATES as Y, buildVideoArgs as Yt, EXPRESSION_INJECTED_NOW as Z, isSoftwareDecode as Zt, CompositionFromSourceSchema as _, RESERVED_BINDING_NAMES as _t, CUSTOMIZATION_BLOCK_NAME_PREFIX as a, evaluateAst as at, CompositionNewTargetSchema as b, disarmRoseMemory as bt, CompositionCodeSourceSchema as c, parseExpression as ct, CompositionExpressionSourceSchema as d, EXPRESSION_IDENTIFIER_RE as dt, resolveStreamMaps as en, evaluateExpressionSource as et, CompositionFeatureSchema as f, MAX_EXPRESSION_AST_NODES as ft, CompositionForwardCommandSchema as g, MAX_EXPRESSION_SOURCE_LENGTH as gt, CompositionFieldsFeatureSchema as h, MAX_EXPRESSION_EVAL_STEPS as ht, COMPOSITION_ITEM_KEY_RE as i, createExpressionScope as it, compositionItemFieldPath as j, evaluateSensorEdge as jt, composedDeviceStableId as k, SOURCE_CAP_CHANGED_AT_FIELD as kt, CompositionCommandTargetSchema as l, tokenize as lt, CompositionFieldSourceSchema as m, MAX_EXPRESSION_CALL_ARGS as mt, COMPOSER_ADDON_ID as n, toExpressionValue as nt, CompositionAggregateSourceSchema as o, compileExpression as ot, CompositionFieldReadSchema as p, MAX_EXPRESSION_BINDINGS as pt, HelperSpecSchema as q, buildFfmpegArgs as qt, COMPOSITION_ITEM_ARRAY_PATH as r, validateExpressionSource as rt, CompositionBindingSchema as s, compileExpressionSafe as st, COMPOSED_DEVICE_STABLE_ID_PREFIX as t, evaluateStatefulExpressionCall as tt, CompositionExistingTargetSchema as u, EXPRESSION_COMPILE_CACHE_CAPACITY as ut, CompositionItemEntrySchema as v, EXPRESSION_BUILTINS as vt, MAX_COMPOSITION_CODE_LENGTH as w, ExpressionEvalError as wt, CompositionPassthroughFeatureSchema as x, evaluateCount as xt, CompositionLiteralBindingSchema as y, EXPRESSION_BUILTIN_NAMES as yt, AGGREGATE_REDUCERS as z, FFMPEG_RELEASE as zt };
|