@camstack/types 1.2.405 → 1.2.407
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 +21 -2
- package/dist/addon.mjs +21 -2
- package/dist/capabilities/battery.cap.d.ts +46 -0
- package/dist/capabilities/capability-definition.d.ts +8 -0
- package/dist/capabilities/consumables.cap.d.ts +110 -0
- package/dist/capabilities/customize-catalog.d.ts +72 -0
- package/dist/capabilities/customize-spec.d.ts +202 -0
- package/dist/capabilities/doorbell.cap.d.ts +39 -0
- package/dist/capabilities/index.d.ts +6 -4
- package/dist/capabilities/motion.cap.d.ts +39 -0
- package/dist/capabilities/notification-rules.cap.d.ts +3 -78
- package/dist/capabilities/osd-manager.cap.d.ts +0 -18
- package/dist/capabilities/running-state.cap.d.ts +140 -0
- package/dist/catalogs/sensor-active-state.d.ts +1 -1
- package/dist/client.js +11 -63
- package/dist/client.mjs +11 -63
- package/dist/composition/customize/__fixtures__/refs.d.ts +27 -0
- package/dist/composition/customize/__fixtures__/stored-cases.d.ts +13 -0
- package/dist/composition/customize/event-compile.d.ts +20 -0
- package/dist/composition/customize/event-decode.d.ts +19 -0
- package/dist/composition/customize/event-eval.d.ts +35 -0
- package/dist/composition/customize/event-status.d.ts +49 -0
- package/dist/composition/customize/field-source.d.ts +5 -0
- package/dist/composition/customize/keyed-array-compile.d.ts +26 -0
- package/dist/composition/customize/keyed-array-decode.d.ts +20 -0
- package/dist/composition/customize/keyed-array-expr.d.ts +10 -0
- package/dist/composition/customize/keyed-array-status.d.ts +22 -0
- package/dist/composition/customize/normalize.d.ts +4 -0
- package/dist/composition/customize/override-draft.d.ts +311 -0
- package/dist/composition/customize/scalar-compile.d.ts +13 -0
- package/dist/composition/customize/scalar-decode.d.ts +17 -0
- package/dist/composition/customize/scalar-expr.d.ts +33 -0
- package/dist/composition/customize/scalar-status.d.ts +31 -0
- package/dist/composition/customize/stored.d.ts +15 -0
- package/dist/composition/index.d.ts +0 -1
- package/dist/{composition-CB6PMT9p.mjs → composition-BJ8iAZb3.mjs} +87 -3
- package/dist/{composition-eoYYVfOp.js → composition-CSLSFGTO.js} +87 -3
- package/dist/device/cap-vocabulary/entries/appliances.d.ts +1 -1
- package/dist/enums/event-category.d.ts +4 -0
- package/dist/enums.js +1 -1
- package/dist/enums.mjs +1 -1
- package/dist/{event-category-fDPduoeC.mjs → event-category-Ceif8n-v.mjs} +4 -0
- package/dist/{event-category-CXrwjC3e.js → event-category-DG6Vir8Z.js} +4 -0
- package/dist/expression/builtins.d.ts +7 -18
- package/dist/expression/expression-source.d.ts +14 -2
- package/dist/generated/addon-api.d.ts +14 -0
- package/dist/generated/addon-cap-facts.d.ts +1 -1
- package/dist/generated/cap-status-types.d.ts +3 -1
- package/dist/generated/capability-router-map.d.ts +5 -2
- package/dist/generated/customize-catalog.d.ts +229 -0
- package/dist/generated/device-local-state.d.ts +3 -0
- package/dist/generated/device-proxy.d.ts +3 -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/index.d.ts +16 -0
- package/dist/index.js +2385 -173
- package/dist/index.mjs +2351 -171
- package/dist/interfaces/config-ui.d.ts +69 -2
- package/dist/node.js +1 -1
- package/dist/node.mjs +1 -1
- package/dist/running-state/defaults.d.ts +6 -0
- package/dist/running-state/from-operation.d.ts +14 -0
- package/dist/{sleep-CHIEEJkY.mjs → sleep-CYfIZzGv.mjs} +7 -3
- package/dist/{sleep-BKS4OPMo.js → sleep-UP964hNP.js} +7 -3
- package/package.json +1 -1
- package/dist/composition/presets/doorbell-feature.d.ts +0 -20
|
@@ -929,7 +929,7 @@ function chooseFfmpegBinary(input) {
|
|
|
929
929
|
* ONE table for everyone who asks "is this device HIGH?": the
|
|
930
930
|
* recorder's `RecordingTriggers.sensorDeviceIds` trigger, the post-analysis
|
|
931
931
|
* sensor markers, the orchestrator's camera-sensors bridge and
|
|
932
|
-
* the sources of a
|
|
932
|
+
* the sources of a pulse (`compilePulseOverride`, D936).
|
|
933
933
|
* A second copy would diverge at the first cap added, and the symptom — "the
|
|
934
934
|
* sensor rings the doorbell but does not record" — is exactly D62.
|
|
935
935
|
*
|
|
@@ -1138,7 +1138,7 @@ var ExpressionEvalError = class extends Error {
|
|
|
1138
1138
|
//#endregion
|
|
1139
1139
|
//#region src/expression/builtins.ts
|
|
1140
1140
|
function isStatefulBuiltin(name) {
|
|
1141
|
-
return name === "rose" || name === "count";
|
|
1141
|
+
return name === "rose" || name === "count" || name === "dwell" || name === "latchedAt";
|
|
1142
1142
|
}
|
|
1143
1143
|
function asFiniteNumber(value, name, index) {
|
|
1144
1144
|
if (typeof value !== "number" || !Number.isFinite(value)) throw new ExpressionEvalError(`${name}: argument ${index + 1} must be a finite number`);
|
|
@@ -1229,6 +1229,57 @@ function disarmRoseMemory(memory) {
|
|
|
1229
1229
|
* input is its own `lastPressedAt`, which only advances on a `rose` edge that
|
|
1230
1230
|
* also emits the press — but an external input can overcount by one.
|
|
1231
1231
|
*/
|
|
1232
|
+
function asNonNegativeMs(value, name, index) {
|
|
1233
|
+
const ms = asFiniteNumber(value, name, index);
|
|
1234
|
+
if (ms < 0) throw new ExpressionEvalError(`${name}: delay must be a non-negative finite number`);
|
|
1235
|
+
return ms;
|
|
1236
|
+
}
|
|
1237
|
+
/**
|
|
1238
|
+
* `dwell(active, onForMs, offForMs)`: unknown until a delay elapses, then holds
|
|
1239
|
+
* the latched boolean through gaps shorter than the opposing delay (D933).
|
|
1240
|
+
*/
|
|
1241
|
+
function evaluateDwell(activeRaw, onForMsRaw, offForMsRaw, call, nowMs, hooks) {
|
|
1242
|
+
const active = asBoolean(activeRaw, "dwell", 0);
|
|
1243
|
+
const onForMs = asNonNegativeMs(onForMsRaw, "dwell", 1);
|
|
1244
|
+
const offForMs = asNonNegativeMs(offForMsRaw, "dwell", 2);
|
|
1245
|
+
if (call.latched === null) {
|
|
1246
|
+
if (call.seenSince === null) call.seenSince = nowMs;
|
|
1247
|
+
const delay = active ? onForMs : offForMs;
|
|
1248
|
+
if (nowMs - call.seenSince >= delay) {
|
|
1249
|
+
call.latched = active;
|
|
1250
|
+
return call.latched;
|
|
1251
|
+
}
|
|
1252
|
+
hooks?.noteDeadline?.(call.seenSince + delay);
|
|
1253
|
+
return null;
|
|
1254
|
+
}
|
|
1255
|
+
if (active === call.latched) {
|
|
1256
|
+
call.pendingSince = null;
|
|
1257
|
+
return call.latched;
|
|
1258
|
+
}
|
|
1259
|
+
if (call.pendingSince === null) call.pendingSince = nowMs;
|
|
1260
|
+
const delay = active ? onForMs : offForMs;
|
|
1261
|
+
if (nowMs - call.pendingSince >= delay) {
|
|
1262
|
+
call.latched = active;
|
|
1263
|
+
call.pendingSince = null;
|
|
1264
|
+
return call.latched;
|
|
1265
|
+
}
|
|
1266
|
+
hooks?.noteDeadline?.(call.pendingSince + delay);
|
|
1267
|
+
return call.latched;
|
|
1268
|
+
}
|
|
1269
|
+
/** `latchedAt(value)`: epoch ms when `value` last changed; null clears the stamp. */
|
|
1270
|
+
function evaluateLatchedAt(value, call, nowMs) {
|
|
1271
|
+
if (value === null) {
|
|
1272
|
+
call.last = null;
|
|
1273
|
+
call.at = null;
|
|
1274
|
+
return null;
|
|
1275
|
+
}
|
|
1276
|
+
if (typeof value !== "boolean" && typeof value !== "number" && typeof value !== "string") return call.at;
|
|
1277
|
+
if (call.last !== value) {
|
|
1278
|
+
call.last = value;
|
|
1279
|
+
call.at = nowMs;
|
|
1280
|
+
}
|
|
1281
|
+
return call.at;
|
|
1282
|
+
}
|
|
1232
1283
|
function evaluateCount(input, call, currentOutput) {
|
|
1233
1284
|
const currentCount = typeof currentOutput === "number" && Number.isFinite(currentOutput) && currentOutput >= 0 ? currentOutput : 0;
|
|
1234
1285
|
if (input === null) {
|
|
@@ -1398,6 +1449,20 @@ var table = {
|
|
|
1398
1449
|
apply: () => {
|
|
1399
1450
|
throw new ExpressionEvalError("count: stateful evaluation context is required");
|
|
1400
1451
|
}
|
|
1452
|
+
},
|
|
1453
|
+
dwell: {
|
|
1454
|
+
minArgs: 3,
|
|
1455
|
+
maxArgs: 3,
|
|
1456
|
+
apply: () => {
|
|
1457
|
+
throw new ExpressionEvalError("dwell: stateful evaluation context is required");
|
|
1458
|
+
}
|
|
1459
|
+
},
|
|
1460
|
+
latchedAt: {
|
|
1461
|
+
minArgs: 1,
|
|
1462
|
+
maxArgs: 1,
|
|
1463
|
+
apply: () => {
|
|
1464
|
+
throw new ExpressionEvalError("latchedAt: stateful evaluation context is required");
|
|
1465
|
+
}
|
|
1401
1466
|
}
|
|
1402
1467
|
};
|
|
1403
1468
|
/** Frozen, null-prototype builtin table. */
|
|
@@ -1975,7 +2040,7 @@ function cloneStatefulExpressionMemory(memory) {
|
|
|
1975
2040
|
disarmRoseNext: memory.disarmRoseNext
|
|
1976
2041
|
};
|
|
1977
2042
|
}
|
|
1978
|
-
function evaluateStatefulExpressionCall(invocation, memory, env) {
|
|
2043
|
+
function evaluateStatefulExpressionCall(invocation, memory, env, hooks) {
|
|
1979
2044
|
const existing = memory.calls.get(invocation.path);
|
|
1980
2045
|
switch (invocation.name) {
|
|
1981
2046
|
case "rose": {
|
|
@@ -1997,6 +2062,25 @@ function evaluateStatefulExpressionCall(invocation, memory, env) {
|
|
|
1997
2062
|
memory.calls.set(invocation.path, call);
|
|
1998
2063
|
return evaluateCount(invocation.args[0], call, env.currentOutput);
|
|
1999
2064
|
}
|
|
2065
|
+
case "dwell": {
|
|
2066
|
+
const call = existing?.kind === "dwell" ? existing : {
|
|
2067
|
+
kind: "dwell",
|
|
2068
|
+
pendingSince: null,
|
|
2069
|
+
latched: null,
|
|
2070
|
+
seenSince: null
|
|
2071
|
+
};
|
|
2072
|
+
memory.calls.set(invocation.path, call);
|
|
2073
|
+
return evaluateDwell(invocation.args[0], invocation.args[1], invocation.args[2], call, env.nowMs, hooks);
|
|
2074
|
+
}
|
|
2075
|
+
case "latchedAt": {
|
|
2076
|
+
const call = existing?.kind === "latchedAt" ? existing : {
|
|
2077
|
+
kind: "latchedAt",
|
|
2078
|
+
last: void 0,
|
|
2079
|
+
at: null
|
|
2080
|
+
};
|
|
2081
|
+
memory.calls.set(invocation.path, call);
|
|
2082
|
+
return evaluateLatchedAt(invocation.args[0], call, env.nowMs);
|
|
2083
|
+
}
|
|
2000
2084
|
}
|
|
2001
2085
|
}
|
|
2002
2086
|
/** The `now` epoch-ms binding is auto-injected into every evaluation and is a
|
|
@@ -929,7 +929,7 @@ function chooseFfmpegBinary(input) {
|
|
|
929
929
|
* ONE table for everyone who asks "is this device HIGH?": the
|
|
930
930
|
* recorder's `RecordingTriggers.sensorDeviceIds` trigger, the post-analysis
|
|
931
931
|
* sensor markers, the orchestrator's camera-sensors bridge and
|
|
932
|
-
* the sources of a
|
|
932
|
+
* the sources of a pulse (`compilePulseOverride`, D936).
|
|
933
933
|
* A second copy would diverge at the first cap added, and the symptom — "the
|
|
934
934
|
* sensor rings the doorbell but does not record" — is exactly D62.
|
|
935
935
|
*
|
|
@@ -1138,7 +1138,7 @@ var ExpressionEvalError = class extends Error {
|
|
|
1138
1138
|
//#endregion
|
|
1139
1139
|
//#region src/expression/builtins.ts
|
|
1140
1140
|
function isStatefulBuiltin(name) {
|
|
1141
|
-
return name === "rose" || name === "count";
|
|
1141
|
+
return name === "rose" || name === "count" || name === "dwell" || name === "latchedAt";
|
|
1142
1142
|
}
|
|
1143
1143
|
function asFiniteNumber(value, name, index) {
|
|
1144
1144
|
if (typeof value !== "number" || !Number.isFinite(value)) throw new ExpressionEvalError(`${name}: argument ${index + 1} must be a finite number`);
|
|
@@ -1229,6 +1229,57 @@ function disarmRoseMemory(memory) {
|
|
|
1229
1229
|
* input is its own `lastPressedAt`, which only advances on a `rose` edge that
|
|
1230
1230
|
* also emits the press — but an external input can overcount by one.
|
|
1231
1231
|
*/
|
|
1232
|
+
function asNonNegativeMs(value, name, index) {
|
|
1233
|
+
const ms = asFiniteNumber(value, name, index);
|
|
1234
|
+
if (ms < 0) throw new ExpressionEvalError(`${name}: delay must be a non-negative finite number`);
|
|
1235
|
+
return ms;
|
|
1236
|
+
}
|
|
1237
|
+
/**
|
|
1238
|
+
* `dwell(active, onForMs, offForMs)`: unknown until a delay elapses, then holds
|
|
1239
|
+
* the latched boolean through gaps shorter than the opposing delay (D933).
|
|
1240
|
+
*/
|
|
1241
|
+
function evaluateDwell(activeRaw, onForMsRaw, offForMsRaw, call, nowMs, hooks) {
|
|
1242
|
+
const active = asBoolean(activeRaw, "dwell", 0);
|
|
1243
|
+
const onForMs = asNonNegativeMs(onForMsRaw, "dwell", 1);
|
|
1244
|
+
const offForMs = asNonNegativeMs(offForMsRaw, "dwell", 2);
|
|
1245
|
+
if (call.latched === null) {
|
|
1246
|
+
if (call.seenSince === null) call.seenSince = nowMs;
|
|
1247
|
+
const delay = active ? onForMs : offForMs;
|
|
1248
|
+
if (nowMs - call.seenSince >= delay) {
|
|
1249
|
+
call.latched = active;
|
|
1250
|
+
return call.latched;
|
|
1251
|
+
}
|
|
1252
|
+
hooks?.noteDeadline?.(call.seenSince + delay);
|
|
1253
|
+
return null;
|
|
1254
|
+
}
|
|
1255
|
+
if (active === call.latched) {
|
|
1256
|
+
call.pendingSince = null;
|
|
1257
|
+
return call.latched;
|
|
1258
|
+
}
|
|
1259
|
+
if (call.pendingSince === null) call.pendingSince = nowMs;
|
|
1260
|
+
const delay = active ? onForMs : offForMs;
|
|
1261
|
+
if (nowMs - call.pendingSince >= delay) {
|
|
1262
|
+
call.latched = active;
|
|
1263
|
+
call.pendingSince = null;
|
|
1264
|
+
return call.latched;
|
|
1265
|
+
}
|
|
1266
|
+
hooks?.noteDeadline?.(call.pendingSince + delay);
|
|
1267
|
+
return call.latched;
|
|
1268
|
+
}
|
|
1269
|
+
/** `latchedAt(value)`: epoch ms when `value` last changed; null clears the stamp. */
|
|
1270
|
+
function evaluateLatchedAt(value, call, nowMs) {
|
|
1271
|
+
if (value === null) {
|
|
1272
|
+
call.last = null;
|
|
1273
|
+
call.at = null;
|
|
1274
|
+
return null;
|
|
1275
|
+
}
|
|
1276
|
+
if (typeof value !== "boolean" && typeof value !== "number" && typeof value !== "string") return call.at;
|
|
1277
|
+
if (call.last !== value) {
|
|
1278
|
+
call.last = value;
|
|
1279
|
+
call.at = nowMs;
|
|
1280
|
+
}
|
|
1281
|
+
return call.at;
|
|
1282
|
+
}
|
|
1232
1283
|
function evaluateCount(input, call, currentOutput) {
|
|
1233
1284
|
const currentCount = typeof currentOutput === "number" && Number.isFinite(currentOutput) && currentOutput >= 0 ? currentOutput : 0;
|
|
1234
1285
|
if (input === null) {
|
|
@@ -1398,6 +1449,20 @@ var table = {
|
|
|
1398
1449
|
apply: () => {
|
|
1399
1450
|
throw new ExpressionEvalError("count: stateful evaluation context is required");
|
|
1400
1451
|
}
|
|
1452
|
+
},
|
|
1453
|
+
dwell: {
|
|
1454
|
+
minArgs: 3,
|
|
1455
|
+
maxArgs: 3,
|
|
1456
|
+
apply: () => {
|
|
1457
|
+
throw new ExpressionEvalError("dwell: stateful evaluation context is required");
|
|
1458
|
+
}
|
|
1459
|
+
},
|
|
1460
|
+
latchedAt: {
|
|
1461
|
+
minArgs: 1,
|
|
1462
|
+
maxArgs: 1,
|
|
1463
|
+
apply: () => {
|
|
1464
|
+
throw new ExpressionEvalError("latchedAt: stateful evaluation context is required");
|
|
1465
|
+
}
|
|
1401
1466
|
}
|
|
1402
1467
|
};
|
|
1403
1468
|
/** Frozen, null-prototype builtin table. */
|
|
@@ -1975,7 +2040,7 @@ function cloneStatefulExpressionMemory(memory) {
|
|
|
1975
2040
|
disarmRoseNext: memory.disarmRoseNext
|
|
1976
2041
|
};
|
|
1977
2042
|
}
|
|
1978
|
-
function evaluateStatefulExpressionCall(invocation, memory, env) {
|
|
2043
|
+
function evaluateStatefulExpressionCall(invocation, memory, env, hooks) {
|
|
1979
2044
|
const existing = memory.calls.get(invocation.path);
|
|
1980
2045
|
switch (invocation.name) {
|
|
1981
2046
|
case "rose": {
|
|
@@ -1997,6 +2062,25 @@ function evaluateStatefulExpressionCall(invocation, memory, env) {
|
|
|
1997
2062
|
memory.calls.set(invocation.path, call);
|
|
1998
2063
|
return evaluateCount(invocation.args[0], call, env.currentOutput);
|
|
1999
2064
|
}
|
|
2065
|
+
case "dwell": {
|
|
2066
|
+
const call = existing?.kind === "dwell" ? existing : {
|
|
2067
|
+
kind: "dwell",
|
|
2068
|
+
pendingSince: null,
|
|
2069
|
+
latched: null,
|
|
2070
|
+
seenSince: null
|
|
2071
|
+
};
|
|
2072
|
+
memory.calls.set(invocation.path, call);
|
|
2073
|
+
return evaluateDwell(invocation.args[0], invocation.args[1], invocation.args[2], call, env.nowMs, hooks);
|
|
2074
|
+
}
|
|
2075
|
+
case "latchedAt": {
|
|
2076
|
+
const call = existing?.kind === "latchedAt" ? existing : {
|
|
2077
|
+
kind: "latchedAt",
|
|
2078
|
+
last: void 0,
|
|
2079
|
+
at: null
|
|
2080
|
+
};
|
|
2081
|
+
memory.calls.set(invocation.path, call);
|
|
2082
|
+
return evaluateLatchedAt(invocation.args[0], call, env.nowMs);
|
|
2083
|
+
}
|
|
2000
2084
|
}
|
|
2001
2085
|
}
|
|
2002
2086
|
/** The `now` epoch-ms binding is auto-injected into every evaluation and is a
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CapVocabularySlice } from '../types.js';
|
|
2
|
-
type ApplianceCap = 'vacuum-control' | 'lawn-mower-control' | 'dishwasher' | 'pet-feeder' | 'media-player' | 'consumables' | 'navigation' | 'script-runner' | 'automation-control' | 'notifier' | 'update';
|
|
2
|
+
type ApplianceCap = 'vacuum-control' | 'lawn-mower-control' | 'dishwasher' | 'pet-feeder' | 'media-player' | 'consumables' | 'running-state' | 'navigation' | 'script-runner' | 'automation-control' | 'notifier' | 'update';
|
|
3
3
|
/** The appliance family of the vocabulary. */
|
|
4
4
|
export declare const APPLIANCE_CAP_VOCABULARY: CapVocabularySlice<ApplianceCap>;
|
|
5
5
|
export {};
|
|
@@ -469,6 +469,10 @@ export declare enum EventCategory {
|
|
|
469
469
|
* on the device detail page.
|
|
470
470
|
*/
|
|
471
471
|
DoorbellOnPressed = "doorbell.onPressed",
|
|
472
|
+
/** Mirrors `runningStateCapability.events.onStarted`. */
|
|
473
|
+
RunningStarted = "running.started",
|
|
474
|
+
/** Mirrors `runningStateCapability.events.onFinished`. */
|
|
475
|
+
RunningFinished = "running.finished",
|
|
472
476
|
/**
|
|
473
477
|
* Cap event fired by every device that registers the `event-emitter`
|
|
474
478
|
* capability. Mirrors `eventEmitterCapability.events.onEvent`. Carries
|
package/dist/enums.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_event_category = require("./event-category-
|
|
2
|
+
const require_event_category = require("./event-category-DG6Vir8Z.js");
|
|
3
3
|
//#region src/enums/event-source-type.ts
|
|
4
4
|
var EventSourceType = /* @__PURE__ */ function(EventSourceType) {
|
|
5
5
|
EventSourceType["Addon"] = "addon";
|
package/dist/enums.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as EventCategory } from "./event-category-
|
|
1
|
+
import { t as EventCategory } from "./event-category-Ceif8n-v.mjs";
|
|
2
2
|
//#region src/enums/event-source-type.ts
|
|
3
3
|
var EventSourceType = /* @__PURE__ */ function(EventSourceType) {
|
|
4
4
|
EventSourceType["Addon"] = "addon";
|
|
@@ -470,6 +470,10 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
470
470
|
* on the device detail page.
|
|
471
471
|
*/
|
|
472
472
|
EventCategory["DoorbellOnPressed"] = "doorbell.onPressed";
|
|
473
|
+
/** Mirrors `runningStateCapability.events.onStarted`. */
|
|
474
|
+
EventCategory["RunningStarted"] = "running.started";
|
|
475
|
+
/** Mirrors `runningStateCapability.events.onFinished`. */
|
|
476
|
+
EventCategory["RunningFinished"] = "running.finished";
|
|
473
477
|
/**
|
|
474
478
|
* Cap event fired by every device that registers the `event-emitter`
|
|
475
479
|
* capability. Mirrors `eventEmitterCapability.events.onEvent`. Carries
|
|
@@ -470,6 +470,10 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
470
470
|
* on the device detail page.
|
|
471
471
|
*/
|
|
472
472
|
EventCategory["DoorbellOnPressed"] = "doorbell.onPressed";
|
|
473
|
+
/** Mirrors `runningStateCapability.events.onStarted`. */
|
|
474
|
+
EventCategory["RunningStarted"] = "running.started";
|
|
475
|
+
/** Mirrors `runningStateCapability.events.onFinished`. */
|
|
476
|
+
EventCategory["RunningFinished"] = "running.finished";
|
|
473
477
|
/**
|
|
474
478
|
* Cap event fired by every device that registers the `event-emitter`
|
|
475
479
|
* capability. Mirrors `eventEmitterCapability.events.onEvent`. Carries
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* closed rather than emitting a garbage value.
|
|
17
17
|
*/
|
|
18
18
|
import type { ExpressionValue } from './ast.js';
|
|
19
|
-
import type { CountCallState, RoseCallState, StatefulExpressionMemory } from './expression-source.js';
|
|
19
|
+
import type { CountCallState, DwellCallState, LatchedAtCallState, RoseCallState, StatefulExpressionMemory } from './expression-source.js';
|
|
20
20
|
/** Optional runtime hooks the evaluator threads through to builtins. */
|
|
21
21
|
export interface ExpressionEvalHooks {
|
|
22
22
|
/** Convert `value` from unit `from` to unit `to`; `null` when the pair is
|
|
@@ -41,7 +41,7 @@ export interface ExpressionBuiltin {
|
|
|
41
41
|
readonly maxArgs: number;
|
|
42
42
|
readonly apply: (args: readonly ExpressionValue[], hooks: ExpressionEvalHooks) => ExpressionValue;
|
|
43
43
|
}
|
|
44
|
-
export type StatefulExpressionBuiltin = 'rose' | 'count';
|
|
44
|
+
export type StatefulExpressionBuiltin = 'rose' | 'count' | 'dwell' | 'latchedAt';
|
|
45
45
|
export declare function isStatefulBuiltin(name: string): name is StatefulExpressionBuiltin;
|
|
46
46
|
export declare function evaluateRose(level: unknown, changedAt: unknown, debounceMs: unknown, call: RoseCallState, field: StatefulExpressionMemory, env: {
|
|
47
47
|
readonly currentOutput: number | null;
|
|
@@ -51,23 +51,12 @@ export declare function evaluateRose(level: unknown, changedAt: unknown, debounc
|
|
|
51
51
|
/** Next evaluation of every `rose` call baselines without rising. */
|
|
52
52
|
export declare function disarmRoseMemory(memory: StatefulExpressionMemory): void;
|
|
53
53
|
/**
|
|
54
|
-
* `
|
|
55
|
-
*
|
|
56
|
-
* - an answered `null` ("never happened") primes it with no high-water, so the
|
|
57
|
-
* next finite value is a real advance and counts 1;
|
|
58
|
-
* - an answered finite value primes it with that value as the high-water and
|
|
59
|
-
* no increment — it is history, not an event;
|
|
60
|
-
* - anything else (a read that did not answer reaches here as neither) does
|
|
61
|
-
* NOT prime it (D393: unknown is not null).
|
|
62
|
-
* An unavailable binding never reaches this function at all: the field is
|
|
63
|
-
* judged unavailable before the expression runs.
|
|
64
|
-
*
|
|
65
|
-
* Edge case, accepted: an input that answers `null` and LATER reports a
|
|
66
|
-
* historical value (a sensor's `lastChangedAt` that was null until its first
|
|
67
|
-
* report) counts that value once. For the doorbell it cannot happen — its
|
|
68
|
-
* input is its own `lastPressedAt`, which only advances on a `rose` edge that
|
|
69
|
-
* also emits the press — but an external input can overcount by one.
|
|
54
|
+
* `dwell(active, onForMs, offForMs)`: unknown until a delay elapses, then holds
|
|
55
|
+
* the latched boolean through gaps shorter than the opposing delay (D933).
|
|
70
56
|
*/
|
|
57
|
+
export declare function evaluateDwell(activeRaw: unknown, onForMsRaw: unknown, offForMsRaw: unknown, call: DwellCallState, nowMs: number, hooks?: ExpressionEvalHooks): boolean | null;
|
|
58
|
+
/** `latchedAt(value)`: epoch ms when `value` last changed; null clears the stamp. */
|
|
59
|
+
export declare function evaluateLatchedAt(value: unknown, call: LatchedAtCallState, nowMs: number): number | null;
|
|
71
60
|
export declare function evaluateCount(input: unknown, call: CountCallState, currentOutput: unknown): number;
|
|
72
61
|
/** Frozen, null-prototype builtin table. */
|
|
73
62
|
export declare const EXPRESSION_BUILTINS: Readonly<Record<string, ExpressionBuiltin>>;
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* positions (derive a value, gate a trigger, compute an argument).
|
|
10
10
|
*/
|
|
11
11
|
import type { ExpressionValue } from './ast.js';
|
|
12
|
+
import { type ExpressionEvalHooks } from './builtins.js';
|
|
12
13
|
import { type ExpressionEvalOptions, type StatefulCallInvocation } from './evaluator.js';
|
|
13
14
|
export interface RoseCallState {
|
|
14
15
|
readonly kind: 'rose';
|
|
@@ -27,7 +28,18 @@ export interface CountCallState {
|
|
|
27
28
|
/** Whether a read has ANSWERED yet (a finite value or `null`); `highWater` means nothing before. */
|
|
28
29
|
primed: boolean;
|
|
29
30
|
}
|
|
30
|
-
export
|
|
31
|
+
export interface DwellCallState {
|
|
32
|
+
readonly kind: 'dwell';
|
|
33
|
+
pendingSince: number | null;
|
|
34
|
+
latched: boolean | null;
|
|
35
|
+
seenSince: number | null;
|
|
36
|
+
}
|
|
37
|
+
export interface LatchedAtCallState {
|
|
38
|
+
readonly kind: 'latchedAt';
|
|
39
|
+
last: ExpressionValue | undefined;
|
|
40
|
+
at: number | null;
|
|
41
|
+
}
|
|
42
|
+
export type StatefulCallState = RoseCallState | CountCallState | DwellCallState | LatchedAtCallState;
|
|
31
43
|
export interface StatefulExpressionMemory {
|
|
32
44
|
readonly calls: Map<string, StatefulCallState>;
|
|
33
45
|
acceptedEdgeAt: number | null;
|
|
@@ -44,7 +56,7 @@ export interface StatefulExpressionEnvironment {
|
|
|
44
56
|
readonly startedAtMs: number;
|
|
45
57
|
readonly nowMs: number;
|
|
46
58
|
}
|
|
47
|
-
export declare function evaluateStatefulExpressionCall(invocation: StatefulCallInvocation, memory: StatefulExpressionMemory, env: StatefulExpressionEnvironment): ExpressionValue;
|
|
59
|
+
export declare function evaluateStatefulExpressionCall(invocation: StatefulCallInvocation, memory: StatefulExpressionMemory, env: StatefulExpressionEnvironment, hooks?: ExpressionEvalHooks): ExpressionValue;
|
|
48
60
|
/** The `now` epoch-ms binding is auto-injected into every evaluation and is a
|
|
49
61
|
* reserved binding name (authors may not rebind it). */
|
|
50
62
|
export declare const EXPRESSION_INJECTED_NOW = "now";
|
|
@@ -8541,6 +8541,20 @@ export type AppRouter = TrpcCoreRouter<{
|
|
|
8541
8541
|
meta: object;
|
|
8542
8542
|
}>;
|
|
8543
8543
|
}>>;
|
|
8544
|
+
runningState: TRPCBuiltRouter<{
|
|
8545
|
+
ctx: TrpcContext;
|
|
8546
|
+
meta: object;
|
|
8547
|
+
errorShape: AugmentedErrorShape;
|
|
8548
|
+
transformer: true;
|
|
8549
|
+
}, TRPCDecorateCreateRouterOptions<{
|
|
8550
|
+
getStatus: TRPCQueryProcedure<{
|
|
8551
|
+
input: {
|
|
8552
|
+
[x: string]: unknown;
|
|
8553
|
+
} & z.input<typeof DEVICE_STATUS_METHOD.getStatus.input>;
|
|
8554
|
+
output: z.infer<typeof DEVICE_STATUS_METHOD.getStatus.output>;
|
|
8555
|
+
meta: object;
|
|
8556
|
+
}>;
|
|
8557
|
+
}>>;
|
|
8544
8558
|
sceneMonitor: TRPCBuiltRouter<{
|
|
8545
8559
|
ctx: TrpcContext;
|
|
8546
8560
|
meta: object;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* `ALL_CAPABILITY_DEFINITIONS` (the whole Zod schema graph, ~+100 MB heap per
|
|
6
6
|
* runner). See docs/decisions/adr-0028.md.
|
|
7
7
|
*
|
|
8
|
-
* Coverage: 1 advance-derived caps,
|
|
8
|
+
* Coverage: 1 advance-derived caps, 74 caps with 367 state leaves.
|
|
9
9
|
*/
|
|
10
10
|
/** A bindable scalar in a capability's runtime state. */
|
|
11
11
|
export interface CapStateLeaf {
|
|
@@ -59,6 +59,7 @@ import type { PtzAutotrackStatusSchema } from '../capabilities/ptz-autotrack.cap
|
|
|
59
59
|
import type { recordingArchiveCapability } from '../capabilities/recording-archive.cap.js';
|
|
60
60
|
import type { RecordingOnboardStatusSchema } from '../capabilities/recording-onboard.cap.js';
|
|
61
61
|
import type { RecordingSignalStatusSchema } from '../capabilities/recording-signal.cap.js';
|
|
62
|
+
import type { RunningStateStatusSchema } from '../capabilities/running-state.cap.js';
|
|
62
63
|
import type { SceneMonitorStatusSchema } from '../capabilities/scene-monitor.cap.js';
|
|
63
64
|
import type { ScriptRunnerStatusSchema } from '../capabilities/script-runner.cap.js';
|
|
64
65
|
import type { SmokeStatusSchema } from '../capabilities/smoke.cap.js';
|
|
@@ -139,6 +140,7 @@ export type CapStatusTypeMap = {
|
|
|
139
140
|
readonly 'recording-archive': z.infer<(typeof recordingArchiveCapability)['status']['schema']>;
|
|
140
141
|
readonly 'recording-onboard': z.infer<typeof RecordingOnboardStatusSchema>;
|
|
141
142
|
readonly 'recording-signal': z.infer<typeof RecordingSignalStatusSchema>;
|
|
143
|
+
readonly 'running-state': z.infer<typeof RunningStateStatusSchema>;
|
|
142
144
|
readonly 'scene-monitor': z.infer<typeof SceneMonitorStatusSchema>;
|
|
143
145
|
readonly 'script-runner': z.infer<typeof ScriptRunnerStatusSchema>;
|
|
144
146
|
readonly 'smoke': z.infer<typeof SmokeStatusSchema>;
|
|
@@ -161,4 +163,4 @@ export type CapNameWithStatus = keyof CapStatusTypeMap;
|
|
|
161
163
|
* aggregator to enumerate caps whose `status` should be polled +
|
|
162
164
|
* streamed via `subscribeDeviceStatusAggregate`.
|
|
163
165
|
*/
|
|
164
|
-
export declare const CAP_NAMES_WITH_STATUS: readonly ["accessories", "air-quality-sensor", "alarm-panel", "ambient-light-sensor", "automation-control", "battery", "binary", "brightness", "broker", "camera-credentials", "carbon-monoxide", "climate-control", "color", "connectivity", "consumables", "contact", "control", "cover", "day-night", "device-adoption", "device-discovery", "device-export", "device-status", "dishwasher", "doorbell", "enum-sensor", "event-emitter", "fan-control", "feature-probe", "flood", "gas", "heating-valve", "humidifier", "humidity-sensor", "image", "image-settings", "intercom", "lawn-mower-control", "lock-control", "media-player", "motion", "motion-trigger", "motion-zones", "mqtt-broker", "native-object-detection", "navigation", "network-link", "notifier", "numeric-sensor", "osd", "pet-feeder", "power-meter", "presence", "pressure-sensor", "privacy-mask", "ptz", "ptz-autotrack", "recording-archive", "recording-onboard", "recording-signal", "scene-monitor", "script-runner", "smoke", "snapshot", "stream-params", "switch", "tamper", "temperature-sensor", "update", "vacuum-control", "valve", "vibration", "water-heater", "weather"];
|
|
166
|
+
export declare const CAP_NAMES_WITH_STATUS: readonly ["accessories", "air-quality-sensor", "alarm-panel", "ambient-light-sensor", "automation-control", "battery", "binary", "brightness", "broker", "camera-credentials", "carbon-monoxide", "climate-control", "color", "connectivity", "consumables", "contact", "control", "cover", "day-night", "device-adoption", "device-discovery", "device-export", "device-status", "dishwasher", "doorbell", "enum-sensor", "event-emitter", "fan-control", "feature-probe", "flood", "gas", "heating-valve", "humidifier", "humidity-sensor", "image", "image-settings", "intercom", "lawn-mower-control", "lock-control", "media-player", "motion", "motion-trigger", "motion-zones", "mqtt-broker", "native-object-detection", "navigation", "network-link", "notifier", "numeric-sensor", "osd", "pet-feeder", "power-meter", "presence", "pressure-sensor", "privacy-mask", "ptz", "ptz-autotrack", "recording-archive", "recording-onboard", "recording-signal", "running-state", "scene-monitor", "script-runner", "smoke", "snapshot", "stream-params", "switch", "tamper", "temperature-sensor", "update", "vacuum-control", "valve", "vibration", "water-heater", "weather"];
|
|
@@ -135,6 +135,7 @@ export { recordingExportCapability } from '../capabilities/recording-export.cap.
|
|
|
135
135
|
export { recordingOnboardCapability } from '../capabilities/recording-onboard.cap.js';
|
|
136
136
|
export { recordingSignalCapability } from '../capabilities/recording-signal.cap.js';
|
|
137
137
|
export { recordsCapability } from '../capabilities/records.cap.js';
|
|
138
|
+
export { runningStateCapability } from '../capabilities/running-state.cap.js';
|
|
138
139
|
export { sceneMonitorCapability } from '../capabilities/scene-monitor.cap.js';
|
|
139
140
|
export { scriptRunnerCapability } from '../capabilities/script-runner.cap.js';
|
|
140
141
|
export { serverManagementCapability } from '../capabilities/server-management.cap.js';
|
|
@@ -315,6 +316,7 @@ export declare const CAPABILITY_NAMES: {
|
|
|
315
316
|
readonly recordingOnboard: 'recording-onboard';
|
|
316
317
|
readonly recordingSignal: 'recording-signal';
|
|
317
318
|
readonly records: 'records';
|
|
319
|
+
readonly runningState: 'running-state';
|
|
318
320
|
readonly sceneMonitor: 'scene-monitor';
|
|
319
321
|
readonly scriptRunner: 'script-runner';
|
|
320
322
|
readonly serverManagement: 'server-management';
|
|
@@ -508,6 +510,7 @@ export interface CapabilityRouterMap<TRouter = unknown> {
|
|
|
508
510
|
readonly recordingOnboard: TRouter;
|
|
509
511
|
readonly recordingSignal: TRouter;
|
|
510
512
|
readonly records: TRouter;
|
|
513
|
+
readonly runningState: TRouter;
|
|
511
514
|
readonly sceneMonitor: TRouter;
|
|
512
515
|
readonly scriptRunner: TRouter;
|
|
513
516
|
readonly serverManagement: TRouter;
|
|
@@ -551,8 +554,8 @@ export interface CapabilityRouterMap<TRouter = unknown> {
|
|
|
551
554
|
readonly zoneRules: TRouter;
|
|
552
555
|
readonly zones: TRouter;
|
|
553
556
|
}
|
|
554
|
-
/** Capability names whose mode is `singleton` (
|
|
555
|
-
export declare const SINGLETON_CAPABILITY_NAMES: readonly ['accessories', 'addon-pages', 'addon-settings', 'addon-widgets', 'addons', 'admin-ui', 'air-quality-sensor', 'alarm-panel', 'alerts', 'ambient-light-sensor', 'audio-analysis', 'audio-analyzer', 'audio-codec', 'audio-metrics', 'automation-control', 'backup', 'battery', 'binary', 'brightness', 'button', 'calendars', 'camera-credentials', 'camera-grid-layout', 'camera-pipeline-config', 'camera-streams', 'carbon-monoxide', 'climate-control', 'color', 'composer', 'connectivity', 'consumables', 'contact', 'control', 'core-blocks', 'cover', 'database-snapshot', 'day-night', 'decoder', 'detection-pipeline', 'device-admin-link', 'device-credentials', 'device-discovery', 'device-history', 'device-manager', 'device-ops', 'device-state', 'device-status', 'dishwasher', 'doorbell', 'enum-sensor', 'event-emitter', 'face-gallery', 'fan-control', 'feature-probe', 'filesystem-browse', 'flood', 'gas', 'heating-valve', 'humidifier', 'humidity-sensor', 'image', 'image-settings', 'integrations', 'intercom', 'keychain', 'keychain-admin', 'lawn-mower-control', 'llm-runtime', 'local-network', 'lock-control', 'media-player', 'metrics-provider', 'model-convert', 'model-distributor', 'motion', 'motion-detection', 'motion-trigger', 'motion-zones', 'native-object-detection', 'navigation', 'network-link', 'network-quality', 'node-certificates', 'nodes', 'notification-rules', 'notifier', 'numeric-sensor', 'oidc-connections', 'osd', 'osd-manager', 'pet-feeder', 'pipeline-analytics', 'pipeline-executor', 'pipeline-orchestrator', 'pipeline-runner', 'plate-gallery', 'platform-probe', 'power-meter', 'presence', 'pressure-sensor', 'privacy-mask', 'ptz', 'ptz-autotrack', 'reboot', 'record-entries', 'recording-archive', 'recording-export', 'recording-onboard', 'recording-signal', 'records', 'scene-monitor', 'script-runner', 'server-management', 'settings-store', 'smoke', 'snapshot', 'sso-bridge', 'storage', 'storage-admin', 'storage-migration', 'stream-broker', 'stream-catalog', 'stream-params', 'stream-signals', 'switch', 'system', 'tamper', 'temperature-sensor', 'terminal-session', 'toast', 'training', 'update', 'user-management', 'vacuum-control', 'valve', 'vector-store', 'vibration', 'viewer-ui', 'water-heater', 'weather', 'webrtc-session', 'zone-analytics', 'zone-rules', 'zones'];
|
|
557
|
+
/** Capability names whose mode is `singleton` (145 caps). */
|
|
558
|
+
export declare const SINGLETON_CAPABILITY_NAMES: readonly ['accessories', 'addon-pages', 'addon-settings', 'addon-widgets', 'addons', 'admin-ui', 'air-quality-sensor', 'alarm-panel', 'alerts', 'ambient-light-sensor', 'audio-analysis', 'audio-analyzer', 'audio-codec', 'audio-metrics', 'automation-control', 'backup', 'battery', 'binary', 'brightness', 'button', 'calendars', 'camera-credentials', 'camera-grid-layout', 'camera-pipeline-config', 'camera-streams', 'carbon-monoxide', 'climate-control', 'color', 'composer', 'connectivity', 'consumables', 'contact', 'control', 'core-blocks', 'cover', 'database-snapshot', 'day-night', 'decoder', 'detection-pipeline', 'device-admin-link', 'device-credentials', 'device-discovery', 'device-history', 'device-manager', 'device-ops', 'device-state', 'device-status', 'dishwasher', 'doorbell', 'enum-sensor', 'event-emitter', 'face-gallery', 'fan-control', 'feature-probe', 'filesystem-browse', 'flood', 'gas', 'heating-valve', 'humidifier', 'humidity-sensor', 'image', 'image-settings', 'integrations', 'intercom', 'keychain', 'keychain-admin', 'lawn-mower-control', 'llm-runtime', 'local-network', 'lock-control', 'media-player', 'metrics-provider', 'model-convert', 'model-distributor', 'motion', 'motion-detection', 'motion-trigger', 'motion-zones', 'native-object-detection', 'navigation', 'network-link', 'network-quality', 'node-certificates', 'nodes', 'notification-rules', 'notifier', 'numeric-sensor', 'oidc-connections', 'osd', 'osd-manager', 'pet-feeder', 'pipeline-analytics', 'pipeline-executor', 'pipeline-orchestrator', 'pipeline-runner', 'plate-gallery', 'platform-probe', 'power-meter', 'presence', 'pressure-sensor', 'privacy-mask', 'ptz', 'ptz-autotrack', 'reboot', 'record-entries', 'recording-archive', 'recording-export', 'recording-onboard', 'recording-signal', 'records', 'running-state', 'scene-monitor', 'script-runner', 'server-management', 'settings-store', 'smoke', 'snapshot', 'sso-bridge', 'storage', 'storage-admin', 'storage-migration', 'stream-broker', 'stream-catalog', 'stream-params', 'stream-signals', 'switch', 'system', 'tamper', 'temperature-sensor', 'terminal-session', 'toast', 'training', 'update', 'user-management', 'vacuum-control', 'valve', 'vector-store', 'vibration', 'viewer-ui', 'water-heater', 'weather', 'webrtc-session', 'zone-analytics', 'zone-rules', 'zones'];
|
|
556
559
|
/** Union of singleton capability names (literal string union). */
|
|
557
560
|
export type SingletonCapabilityName = typeof SINGLETON_CAPABILITY_NAMES[number];
|
|
558
561
|
/** Capability names whose mode is `collection` (35 caps). */
|