@camstack/addon-post-analysis 1.2.655 → 1.2.656
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 +6 -0
- package/dist/{clip-model-registry-C-en5vSD.js → clip-model-registry-BQ_2RsIp.js} +473 -5
- package/dist/{clip-model-registry-_b3KHYFm.mjs → clip-model-registry-C06M8A8U.mjs} +473 -5
- package/dist/embedding-encoder/index.js +1 -1
- package/dist/embedding-encoder/index.mjs +1 -1
- package/dist/pipeline-analytics/_stub.js +2 -2
- package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-CF-Mts9j.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-8vah5-KD.mjs} +2 -2
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-YXyP9GJm.mjs +26 -0
- package/dist/pipeline-analytics/{_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DXQUFp7P.mjs → _virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-gv38vKug.mjs} +1 -1
- package/dist/pipeline-analytics/{hostInit-BSfz5s98.mjs → hostInit-0O7AUcsV.mjs} +2 -2
- package/dist/pipeline-analytics/index.js +20 -2
- package/dist/pipeline-analytics/index.mjs +20 -2
- package/dist/pipeline-analytics/remoteEntry.js +1 -1
- package/package.json +1 -1
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-C7OJ7wek.mjs +0 -26
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.656] - 2026-10-31
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- A lock reporting door-open counts as an opening for the alarm.
|
|
15
|
+
|
|
10
16
|
## [1.2.655] - 2026-10-31
|
|
11
17
|
|
|
12
18
|
### Changed
|
|
@@ -5676,7 +5676,7 @@ var ZodIssueCode = {
|
|
|
5676
5676
|
var ZodFirstPartyTypeKind;
|
|
5677
5677
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5678
5678
|
//#endregion
|
|
5679
|
-
//#region ../types/dist/sleep-
|
|
5679
|
+
//#region ../types/dist/sleep-SX9bkW3_.mjs
|
|
5680
5680
|
/**
|
|
5681
5681
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5682
5682
|
* window to float samples (D455).
|
|
@@ -9347,6 +9347,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
9347
9347
|
"remote-layout-components",
|
|
9348
9348
|
"running-state",
|
|
9349
9349
|
"scene-monitor",
|
|
9350
|
+
"schedulers",
|
|
9350
9351
|
"script-runner",
|
|
9351
9352
|
"server-management",
|
|
9352
9353
|
"settings-store",
|
|
@@ -10292,7 +10293,8 @@ Object.freeze({
|
|
|
10292
10293
|
"unlocked",
|
|
10293
10294
|
"locking",
|
|
10294
10295
|
"unlocking",
|
|
10295
|
-
"jammed"
|
|
10296
|
+
"jammed",
|
|
10297
|
+
"door-open"
|
|
10296
10298
|
]
|
|
10297
10299
|
}],
|
|
10298
10300
|
"media-player": [
|
|
@@ -17786,6 +17788,11 @@ var ACTUATOR_CAP_VOCABULARY = {
|
|
|
17786
17788
|
value: "jammed",
|
|
17787
17789
|
label: t("Jammed", "Inceppata"),
|
|
17788
17790
|
phrase: t("When {device} jams", "Quando {device} si inceppa")
|
|
17791
|
+
},
|
|
17792
|
+
{
|
|
17793
|
+
value: "door-open",
|
|
17794
|
+
label: t("Door open", "Porta aperta"),
|
|
17795
|
+
phrase: t("When the door of {device} opens", "Quando la porta di {device} si apre")
|
|
17789
17796
|
}
|
|
17790
17797
|
],
|
|
17791
17798
|
icon: "lock"
|
|
@@ -21276,6 +21283,7 @@ var SYSTEM_CAP_VOCABULARY = {
|
|
|
21276
21283
|
records: system(INTERNAL),
|
|
21277
21284
|
remote: system("the per-device remote setup — authored in the Customize remote editor, sent through the remote UI"),
|
|
21278
21285
|
"remote-layout-components": system("the palette of the remote template editor — read-only data, never actuated"),
|
|
21286
|
+
schedulers: system("time schedulers — authored on their own page, not device actions"),
|
|
21279
21287
|
"server-management": system(CLUSTER),
|
|
21280
21288
|
"settings-store": system(INTERNAL),
|
|
21281
21289
|
"smtp-provider": system(INTERNAL),
|
|
@@ -42399,6 +42407,122 @@ var AutomationWhenSchema = lazy(() => discriminatedUnion("kind", [
|
|
|
42399
42407
|
StationaryPresentLeafSchema,
|
|
42400
42408
|
ExpressionLeafSchema
|
|
42401
42409
|
]));
|
|
42410
|
+
var EVENT_KINDS = new Set([
|
|
42411
|
+
"device-becomes",
|
|
42412
|
+
"device-event",
|
|
42413
|
+
"schedule",
|
|
42414
|
+
"manual",
|
|
42415
|
+
"interval",
|
|
42416
|
+
"detection",
|
|
42417
|
+
"stationary"
|
|
42418
|
+
]);
|
|
42419
|
+
function isEventLeaf(node) {
|
|
42420
|
+
return EVENT_KINDS.has(node.kind);
|
|
42421
|
+
}
|
|
42422
|
+
function isLeaf(node) {
|
|
42423
|
+
return node.kind !== "all" && node.kind !== "any" && node.kind !== "not";
|
|
42424
|
+
}
|
|
42425
|
+
/** Depth of a tree, root container = 1. A bare leaf is depth 1. */
|
|
42426
|
+
function whenDepth(node) {
|
|
42427
|
+
if (isLeaf(node)) return 1;
|
|
42428
|
+
if (node.kind === "not") return 1 + whenDepth(node.child);
|
|
42429
|
+
let deepest = 0;
|
|
42430
|
+
for (const child of node.children) deepest = Math.max(deepest, whenDepth(child));
|
|
42431
|
+
return 1 + deepest;
|
|
42432
|
+
}
|
|
42433
|
+
/** Leaves only — containers do not count toward the leaf budget. */
|
|
42434
|
+
function countWhenLeaves(node) {
|
|
42435
|
+
if (isLeaf(node)) return 1;
|
|
42436
|
+
if (node.kind === "not") return countWhenLeaves(node.child);
|
|
42437
|
+
let total = 0;
|
|
42438
|
+
for (const child of node.children) total += countWhenLeaves(child);
|
|
42439
|
+
return total;
|
|
42440
|
+
}
|
|
42441
|
+
/** Every leaf with its path (`when`, `when.0`, `when.0.1`, `when.0` under a `not`). */
|
|
42442
|
+
function forEachLeaf(node, visit, path = "when") {
|
|
42443
|
+
if (isLeaf(node)) {
|
|
42444
|
+
visit(node, path);
|
|
42445
|
+
return;
|
|
42446
|
+
}
|
|
42447
|
+
if (node.kind === "not") {
|
|
42448
|
+
forEachLeaf(node.child, visit, `${path}.0`);
|
|
42449
|
+
return;
|
|
42450
|
+
}
|
|
42451
|
+
node.children.forEach((child, i) => {
|
|
42452
|
+
forEachLeaf(child, visit, `${path}.${i}`);
|
|
42453
|
+
});
|
|
42454
|
+
}
|
|
42455
|
+
function hasEventLeaves(node) {
|
|
42456
|
+
let found = false;
|
|
42457
|
+
forEachLeaf(node, (leaf) => {
|
|
42458
|
+
if (isEventLeaf(leaf)) found = true;
|
|
42459
|
+
});
|
|
42460
|
+
return found;
|
|
42461
|
+
}
|
|
42462
|
+
function hasEmptyContainer(node) {
|
|
42463
|
+
if (isLeaf(node)) return false;
|
|
42464
|
+
if (node.kind === "not") return hasEmptyContainer(node.child);
|
|
42465
|
+
if (node.children.length === 0) return true;
|
|
42466
|
+
return node.children.some(hasEmptyContainer);
|
|
42467
|
+
}
|
|
42468
|
+
var LEAF_WORDS = {
|
|
42469
|
+
"device-becomes": "a device value that becomes",
|
|
42470
|
+
"device-event": "a device event",
|
|
42471
|
+
schedule: "a schedule",
|
|
42472
|
+
manual: "a manual run",
|
|
42473
|
+
interval: "an interval",
|
|
42474
|
+
detection: "a detection",
|
|
42475
|
+
stationary: "a parked object appearing or leaving"
|
|
42476
|
+
};
|
|
42477
|
+
function say(kind) {
|
|
42478
|
+
return LEAF_WORDS[kind] ?? kind;
|
|
42479
|
+
}
|
|
42480
|
+
/**
|
|
42481
|
+
* The cheapest set of event leaves that makes `node` true, with negation pushed
|
|
42482
|
+
* down to the leaves first (De Morgan), so `not(any(A, B))` and `all(not A,
|
|
42483
|
+
* not B)` are the same shape to the check. A negated event is its own error: an
|
|
42484
|
+
* event is an instant, "the event did not occur" is true at every other moment.
|
|
42485
|
+
*/
|
|
42486
|
+
function eventNeed(node, path, negated) {
|
|
42487
|
+
if (isLeaf(node)) {
|
|
42488
|
+
if (!isEventLeaf(node)) return { paths: [] };
|
|
42489
|
+
if (negated) return { error: `"not" is applied to ${say(node.kind)} (${path}) — an event is an instant, so "it did not happen" is true at every other moment and can never start a run. Negate a state ("is") instead, or remove the "not"` };
|
|
42490
|
+
return { paths: [{
|
|
42491
|
+
path,
|
|
42492
|
+
kind: node.kind
|
|
42493
|
+
}] };
|
|
42494
|
+
}
|
|
42495
|
+
if (node.kind === "not") return eventNeed(node.child, `${path}.0`, !negated);
|
|
42496
|
+
const conjunctive = node.kind === "all" !== negated;
|
|
42497
|
+
const parts = [];
|
|
42498
|
+
for (let i = 0; i < node.children.length; i += 1) {
|
|
42499
|
+
const child = node.children[i];
|
|
42500
|
+
if (child === void 0) continue;
|
|
42501
|
+
const need = eventNeed(child, `${path}.${i}`, negated);
|
|
42502
|
+
if ("error" in need) return need;
|
|
42503
|
+
parts.push(need);
|
|
42504
|
+
}
|
|
42505
|
+
if (conjunctive) return { paths: parts.flatMap((p) => p.paths) };
|
|
42506
|
+
let best;
|
|
42507
|
+
for (const part of parts) if (best === void 0 || part.paths.length < best.paths.length) best = part;
|
|
42508
|
+
return best ?? { paths: [] };
|
|
42509
|
+
}
|
|
42510
|
+
/**
|
|
42511
|
+
* Author-time bounds and sense check of a `when` tree. Returns `null` when it
|
|
42512
|
+
* is legal, else a message the editor shows verbatim.
|
|
42513
|
+
*/
|
|
42514
|
+
function validateWhenTree(when) {
|
|
42515
|
+
if (hasEmptyContainer(when)) return "a group is empty — group existing rows instead of leaving a container to fill";
|
|
42516
|
+
const depth = whenDepth(when);
|
|
42517
|
+
if (depth > 4) return `the rules nest ${depth} levels deep — the limit is 4. "not (any of …)" is the same as "all of (not …)", which is one level shallower`;
|
|
42518
|
+
const leaves = countWhenLeaves(when);
|
|
42519
|
+
if (leaves > 32) return `the rules use ${leaves} rows — the limit is 32`;
|
|
42520
|
+
const need = eventNeed(when, "when", false);
|
|
42521
|
+
if ("error" in need) return need.error;
|
|
42522
|
+
const [first, second] = need.paths;
|
|
42523
|
+
if (first !== void 0 && second !== void 0) return `${say(first.kind)} (${first.path}) and ${say(second.kind)} (${second.path}) would both have to happen at the same instant, and an event happens at one moment — this can never run. Use "any of" to start on either, or turn one of them into a state ("is") that must already hold`;
|
|
42524
|
+
return null;
|
|
42525
|
+
}
|
|
42402
42526
|
/**
|
|
42403
42527
|
* The recipe shape before the single `when` tree: a flat list of triggers
|
|
42404
42528
|
* (OR'd, each an instant) and an optional condition tree. Stored recipes —
|
|
@@ -42754,6 +42878,187 @@ function convertLegacyRecipe(legacy) {
|
|
|
42754
42878
|
var AutomationRecipeSchema = union([CurrentAutomationRecipeSchema, LegacyAutomationRecipeSchema.transform(convertLegacyRecipe)]);
|
|
42755
42879
|
new Set(Object.values(COCO_TO_MACRO.mapping));
|
|
42756
42880
|
/**
|
|
42881
|
+
* Schedulers (D983) — an entity that performs actions over the day.
|
|
42882
|
+
*
|
|
42883
|
+
* A scheduler has profiles; a profile has weekdays and a timeline of POINTS.
|
|
42884
|
+
* A point is an `edge` (run once at its time), a `hold` (from this point until
|
|
42885
|
+
* the next point of the profile, keep the steps' effects true) or a `release`
|
|
42886
|
+
* (end the current hold without acting). The scheduler AND each profile carry
|
|
42887
|
+
* a manual `enabled` flag and an optional `activeWhen`: a `when` STATE tree
|
|
42888
|
+
* (facts only — an event leaf is an instant and cannot be "in force").
|
|
42889
|
+
*
|
|
42890
|
+
* This file is the data half: the schemas, and the author-time rules that
|
|
42891
|
+
* decide whether a scheduler can be saved at all (a hold needs an action that
|
|
42892
|
+
* leads to a state; a sun point needs the site location). It holds no runtime.
|
|
42893
|
+
*/
|
|
42894
|
+
/** A `when` tree that is a STATE: no event leaf, and legal as a tree. */
|
|
42895
|
+
var SchedulerStateTreeSchema = AutomationWhenSchema.superRefine((when, ctx) => {
|
|
42896
|
+
if (hasEventLeaves(when)) {
|
|
42897
|
+
ctx.addIssue({
|
|
42898
|
+
code: "custom",
|
|
42899
|
+
message: "a scheduler condition is a state — an event (\"becomes\", \"detects\", \"at a time\") is an instant and cannot be in force"
|
|
42900
|
+
});
|
|
42901
|
+
return;
|
|
42902
|
+
}
|
|
42903
|
+
const problem = validateWhenTree(when);
|
|
42904
|
+
if (problem !== null) ctx.addIssue({
|
|
42905
|
+
code: "custom",
|
|
42906
|
+
message: problem
|
|
42907
|
+
});
|
|
42908
|
+
});
|
|
42909
|
+
/** A point's moment: a clock time or a sun event. A one-shot date is not a position on a day. */
|
|
42910
|
+
var SchedulerTimeSpecSchema = TimeSpecSchema.refine((spec) => spec.kind !== "date", { message: "a scheduler point is a clock time or a sun event — a one-shot date has no place on a timeline" });
|
|
42911
|
+
var SchedulerPointModeSchema = _enum([
|
|
42912
|
+
"edge",
|
|
42913
|
+
"hold",
|
|
42914
|
+
"release"
|
|
42915
|
+
]);
|
|
42916
|
+
/** What a hold does when someone changes the device by hand. */
|
|
42917
|
+
var HoldOverrideSchema = discriminatedUnion("mode", [object({ mode: literal("respect") }), object({
|
|
42918
|
+
mode: literal("reassert"),
|
|
42919
|
+
/** How long the manual state is left alone before the hold puts its own back. */
|
|
42920
|
+
graceMs: number().int().min(0).max(24 * 36e5)
|
|
42921
|
+
})]);
|
|
42922
|
+
/** A missed edge up to this late still runs. */
|
|
42923
|
+
var DEFAULT_MAX_LATE_MS = 10 * 6e4;
|
|
42924
|
+
var SchedulerPointSchema = object({
|
|
42925
|
+
id: string().min(1).max(64),
|
|
42926
|
+
at: SchedulerTimeSpecSchema,
|
|
42927
|
+
mode: SchedulerPointModeSchema,
|
|
42928
|
+
/** The actions of an `edge` or `hold`; a `release` has none. */
|
|
42929
|
+
steps: array(ActionStepSchema).max(20).default([]),
|
|
42930
|
+
/** Checked when the point runs (an edge) or is applied (a hold). */
|
|
42931
|
+
conditions: SchedulerStateTreeSchema.optional(),
|
|
42932
|
+
/** Hold only; absent means `respect`. */
|
|
42933
|
+
override: HoldOverrideSchema.optional(),
|
|
42934
|
+
/** Hold only: re-applications per window; absent means {@link DEFAULT_MAX_HOLD_ATTEMPTS}. */
|
|
42935
|
+
maxHoldAttempts: number().int().min(1).max(20).optional()
|
|
42936
|
+
});
|
|
42937
|
+
var SchedulerProfileSchema = object({
|
|
42938
|
+
id: string().min(1).max(64),
|
|
42939
|
+
name: string().min(1).max(120),
|
|
42940
|
+
enabled: boolean().default(true),
|
|
42941
|
+
activeWhen: SchedulerStateTreeSchema.optional(),
|
|
42942
|
+
days: array(WeekdayKeySchema).min(1).max(7),
|
|
42943
|
+
points: array(SchedulerPointSchema).max(50)
|
|
42944
|
+
});
|
|
42945
|
+
/** What an operator writes. */
|
|
42946
|
+
var SchedulerInputSchema = object({
|
|
42947
|
+
name: string().min(1).max(120),
|
|
42948
|
+
enabled: boolean().default(true),
|
|
42949
|
+
activeWhen: SchedulerStateTreeSchema.optional(),
|
|
42950
|
+
/** Higher wins when two holds want the same device in different states. */
|
|
42951
|
+
priority: number().int().min(0).max(100).default(0),
|
|
42952
|
+
maxLateMs: number().int().min(1e3).max(24 * 36e5).default(DEFAULT_MAX_LATE_MS),
|
|
42953
|
+
profiles: array(SchedulerProfileSchema).max(20)
|
|
42954
|
+
});
|
|
42955
|
+
var SchedulerSchema = SchedulerInputSchema.extend({
|
|
42956
|
+
id: string().min(1),
|
|
42957
|
+
createdAt: number(),
|
|
42958
|
+
updatedAt: number()
|
|
42959
|
+
});
|
|
42960
|
+
/** Every outcome a scheduler reports to the runs ledger (`AutomationRunTrace.scheduler`). */
|
|
42961
|
+
var SchedulerOutcomeSchema = _enum([
|
|
42962
|
+
"done",
|
|
42963
|
+
"missed",
|
|
42964
|
+
"inactive",
|
|
42965
|
+
"condition-false",
|
|
42966
|
+
"failed",
|
|
42967
|
+
"held",
|
|
42968
|
+
"gave-up",
|
|
42969
|
+
"overridden",
|
|
42970
|
+
"suspended-manual"
|
|
42971
|
+
]);
|
|
42972
|
+
_enum([
|
|
42973
|
+
"not-found",
|
|
42974
|
+
"invalid-scheduler",
|
|
42975
|
+
"invalid-date"
|
|
42976
|
+
]);
|
|
42977
|
+
var LOCAL_DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
|
|
42978
|
+
/** One point of the day, placed. `at` is `null` when the sun never crosses that day. */
|
|
42979
|
+
var SchedulerPreviewPointSchema = object({
|
|
42980
|
+
pointId: string(),
|
|
42981
|
+
mode: SchedulerPointModeSchema,
|
|
42982
|
+
at: number().nullable(),
|
|
42983
|
+
/** A hold: when its window ends (the next point, else the end of the day). */
|
|
42984
|
+
until: number().nullable(),
|
|
42985
|
+
/** The point's steps are held on a different scheduler's claim at this time — see `conflicts`. */
|
|
42986
|
+
stepCount: number().int()
|
|
42987
|
+
});
|
|
42988
|
+
var SchedulerPreviewSchema = object({
|
|
42989
|
+
schedulerId: string(),
|
|
42990
|
+
/** The site-local day previewed. */
|
|
42991
|
+
date: string().regex(LOCAL_DATE_PATTERN),
|
|
42992
|
+
timeZone: string(),
|
|
42993
|
+
/** Why no profile is in force, or `null` when one is. */
|
|
42994
|
+
idleReason: string().nullable(),
|
|
42995
|
+
/** The profile in force that day: first in list order whose rules hold. */
|
|
42996
|
+
profileId: string().nullable(),
|
|
42997
|
+
points: array(SchedulerPreviewPointSchema)
|
|
42998
|
+
});
|
|
42999
|
+
/** Two holds that want the same device in different states at the same time. */
|
|
43000
|
+
var SchedulerConflictSchema = object({
|
|
43001
|
+
deviceId: number().int(),
|
|
43002
|
+
cap: string(),
|
|
43003
|
+
field: string(),
|
|
43004
|
+
mine: object({
|
|
43005
|
+
profileId: string(),
|
|
43006
|
+
pointId: string(),
|
|
43007
|
+
value: union([
|
|
43008
|
+
string(),
|
|
43009
|
+
number(),
|
|
43010
|
+
boolean()
|
|
43011
|
+
]),
|
|
43012
|
+
priority: number().int()
|
|
43013
|
+
}),
|
|
43014
|
+
other: object({
|
|
43015
|
+
schedulerId: string(),
|
|
43016
|
+
schedulerName: string(),
|
|
43017
|
+
profileId: string(),
|
|
43018
|
+
pointId: string(),
|
|
43019
|
+
value: union([
|
|
43020
|
+
string(),
|
|
43021
|
+
number(),
|
|
43022
|
+
boolean()
|
|
43023
|
+
]),
|
|
43024
|
+
priority: number().int()
|
|
43025
|
+
}),
|
|
43026
|
+
/** The overlapping stretch, as site-local minutes of the day. */
|
|
43027
|
+
fromMinute: number().int(),
|
|
43028
|
+
toMinute: number().int(),
|
|
43029
|
+
/** `mine` | `other` | `tie` — who holds when it happens (a tie: the one that started first). */
|
|
43030
|
+
winner: _enum([
|
|
43031
|
+
"mine",
|
|
43032
|
+
"other",
|
|
43033
|
+
"tie"
|
|
43034
|
+
])
|
|
43035
|
+
});
|
|
43036
|
+
var HoldTargetStatusSchema = _enum([
|
|
43037
|
+
"pending",
|
|
43038
|
+
"held",
|
|
43039
|
+
"suspended-manual",
|
|
43040
|
+
"gave-up",
|
|
43041
|
+
"overridden"
|
|
43042
|
+
]);
|
|
43043
|
+
var SchedulerStatusSchema = object({
|
|
43044
|
+
schedulerId: string(),
|
|
43045
|
+
profileId: string().nullable(),
|
|
43046
|
+
/** The hold in force right now, with where each target stands. */
|
|
43047
|
+
hold: object({
|
|
43048
|
+
pointId: string(),
|
|
43049
|
+
until: number(),
|
|
43050
|
+
/** `true` while the scheduler or profile `activeWhen` is false. */
|
|
43051
|
+
suspendedInactive: boolean(),
|
|
43052
|
+
targets: array(object({
|
|
43053
|
+
deviceId: number().int(),
|
|
43054
|
+
cap: string(),
|
|
43055
|
+
field: string(),
|
|
43056
|
+
status: HoldTargetStatusSchema,
|
|
43057
|
+
attempts: number().int()
|
|
43058
|
+
}))
|
|
43059
|
+
}).nullable()
|
|
43060
|
+
});
|
|
43061
|
+
/**
|
|
42757
43062
|
* Run traces — what an automation (or, later, an Action run) DID, node by node,
|
|
42758
43063
|
* so the editor can paint every block green or red with its reason.
|
|
42759
43064
|
*
|
|
@@ -42889,7 +43194,13 @@ var AutomationRunTraceSchema = object({
|
|
|
42889
43194
|
/** How many identical consecutive skips this trace stands for (>= 1). */
|
|
42890
43195
|
repeat: number().int().min(1),
|
|
42891
43196
|
/** When the latest of those repeats happened. */
|
|
42892
|
-
lastAt: number()
|
|
43197
|
+
lastAt: number(),
|
|
43198
|
+
/**
|
|
43199
|
+
* A scheduler point's own outcome (D983). `outcome` carries the closest
|
|
43200
|
+
* automation outcome so a reader that does not know schedulers still reads
|
|
43201
|
+
* the trace; this field says exactly what happened.
|
|
43202
|
+
*/
|
|
43203
|
+
scheduler: SchedulerOutcomeSchema.optional()
|
|
42893
43204
|
});
|
|
42894
43205
|
/**
|
|
42895
43206
|
* What the hub's `runs` ledger holds for one owner (`automation:<blockId>` or
|
|
@@ -46430,6 +46741,7 @@ method(object({
|
|
|
46430
46741
|
kind: "mutation",
|
|
46431
46742
|
auth: "admin"
|
|
46432
46743
|
}), method(object({ blockIds: array(string()) }), object({ states: array(CompositionBlockStateSchema) }), { auth: "admin" });
|
|
46744
|
+
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Gateway, DeviceType.Camera, DeviceType.Lock, DeviceType.Camera, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
46433
46745
|
var NUMBER = {
|
|
46434
46746
|
kind: "fixed",
|
|
46435
46747
|
result: ["number"]
|
|
@@ -67251,6 +67563,43 @@ method(object({}), array(ActionEntrySchema), { auth: "admin" }), method(object({
|
|
|
67251
67563
|
auth: "admin"
|
|
67252
67564
|
});
|
|
67253
67565
|
/**
|
|
67566
|
+
* schedulers — timelines of edge and hold points that perform actions over the
|
|
67567
|
+
* day (D983). Provided by the core-blocks builtin on the hub, beside `actions`:
|
|
67568
|
+
* the same runs ledger (owner `scheduler:<id>`), the same target resolver, the
|
|
67569
|
+
* same step runner.
|
|
67570
|
+
*
|
|
67571
|
+
* The hub runs ONE timer for the next point across every scheduler. A save is
|
|
67572
|
+
* refused with its reason (`[invalid-scheduler] …`) when a hold has a step that
|
|
67573
|
+
* leads to no state, or a sun point has no site location to read.
|
|
67574
|
+
*/
|
|
67575
|
+
var SchedulerIdInput = object({ schedulerId: string().min(1) });
|
|
67576
|
+
method(object({}), array(SchedulerSchema), { auth: "admin" }), method(SchedulerIdInput, object({ scheduler: SchedulerSchema.nullable() }), { auth: "admin" }), method(object({ scheduler: SchedulerInputSchema }), object({ scheduler: SchedulerSchema }), {
|
|
67577
|
+
kind: "mutation",
|
|
67578
|
+
auth: "admin"
|
|
67579
|
+
}), method(object({
|
|
67580
|
+
schedulerId: string().min(1),
|
|
67581
|
+
scheduler: SchedulerInputSchema
|
|
67582
|
+
}), object({ scheduler: SchedulerSchema }), {
|
|
67583
|
+
kind: "mutation",
|
|
67584
|
+
auth: "admin"
|
|
67585
|
+
}), method(SchedulerIdInput, _void(), {
|
|
67586
|
+
kind: "mutation",
|
|
67587
|
+
auth: "admin"
|
|
67588
|
+
}), method(object({
|
|
67589
|
+
schedulerId: string().min(1),
|
|
67590
|
+
profileId: string().min(1).optional(),
|
|
67591
|
+
enabled: boolean()
|
|
67592
|
+
}), object({ scheduler: SchedulerSchema }), {
|
|
67593
|
+
kind: "mutation",
|
|
67594
|
+
auth: "admin"
|
|
67595
|
+
}), method(object({
|
|
67596
|
+
schedulerId: string().min(1),
|
|
67597
|
+
date: string().regex(LOCAL_DATE_PATTERN).optional()
|
|
67598
|
+
}), SchedulerPreviewSchema, { auth: "admin" }), method(object({
|
|
67599
|
+
scheduler: SchedulerInputSchema,
|
|
67600
|
+
schedulerId: string().min(1).optional()
|
|
67601
|
+
}), object({ conflicts: array(SchedulerConflictSchema) }), { auth: "admin" }), method(object({}), array(SchedulerStatusSchema), { auth: "admin" }), method(SchedulerIdInput, object({ traces: array(AutomationRunTraceSchema) }), { auth: "admin" });
|
|
67602
|
+
/**
|
|
67254
67603
|
* actions — the ONE surface for runnable actions, for the UI and for
|
|
67255
67604
|
* automations. Provided by the core-blocks builtin on the hub.
|
|
67256
67605
|
*
|
|
@@ -71556,6 +71905,8 @@ var IntegrationWithStateSchema = object({
|
|
|
71556
71905
|
name: string(),
|
|
71557
71906
|
enabled: boolean(),
|
|
71558
71907
|
info: record(string(), unknown()).readonly(),
|
|
71908
|
+
/** The discovery candidate this integration was set up from (D984). */
|
|
71909
|
+
originStableId: string().optional(),
|
|
71559
71910
|
createdAt: number(),
|
|
71560
71911
|
updatedAt: number(),
|
|
71561
71912
|
processState: string()
|
|
@@ -71566,6 +71917,8 @@ var IntegrationLiteSchema = object({
|
|
|
71566
71917
|
name: string(),
|
|
71567
71918
|
enabled: boolean(),
|
|
71568
71919
|
info: record(string(), unknown()).readonly(),
|
|
71920
|
+
/** The discovery candidate this integration was set up from (D984). */
|
|
71921
|
+
originStableId: string().optional(),
|
|
71569
71922
|
createdAt: number(),
|
|
71570
71923
|
updatedAt: number()
|
|
71571
71924
|
});
|
|
@@ -71663,6 +72016,8 @@ var CreateIntegrationInputSchema = object({
|
|
|
71663
72016
|
name: string(),
|
|
71664
72017
|
enabled: boolean().optional(),
|
|
71665
72018
|
info: record(string(), unknown()).optional(),
|
|
72019
|
+
/** `stableId` of the discovery candidate the form was seeded from (D984). */
|
|
72020
|
+
originStableId: string().optional(),
|
|
71666
72021
|
settings: record(string(), unknown()).optional(),
|
|
71667
72022
|
/** Keys of `settings` the form's schema declares secret (by type) — kept in
|
|
71668
72023
|
* the keychain, not the table (D787). */
|
|
@@ -72443,12 +72798,22 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
|
|
|
72443
72798
|
* reports `LockEntityFeature.OPEN` (bit value 1) in HA
|
|
72444
72799
|
* `supported_features`.
|
|
72445
72800
|
*/
|
|
72801
|
+
/**
|
|
72802
|
+
* `door-open` (D984): the linked door contact reads open, so the bolt cannot be
|
|
72803
|
+
* thrown. It is the lock's REAL reported state, written into the mirrored slice
|
|
72804
|
+
* by the door-contact Customize extension — never a provider's own value, and
|
|
72805
|
+
* never a projection a reader has to compute. Precedence: a native `jammed`
|
|
72806
|
+
* wins; otherwise an open contact reports `door-open` whatever the native state
|
|
72807
|
+
* says (`locked` included); a closed or unknown contact leaves the native state.
|
|
72808
|
+
* A `lock()` is refused while the state is `door-open`; `unlock()` never is.
|
|
72809
|
+
*/
|
|
72446
72810
|
var LockStateSchema = _enum([
|
|
72447
72811
|
"locked",
|
|
72448
72812
|
"unlocked",
|
|
72449
72813
|
"locking",
|
|
72450
72814
|
"unlocking",
|
|
72451
|
-
"jammed"
|
|
72815
|
+
"jammed",
|
|
72816
|
+
"door-open"
|
|
72452
72817
|
]);
|
|
72453
72818
|
var LockControlStatusSchema = object({
|
|
72454
72819
|
/** Lifecycle state of the lock. `jammed` means the motor reported
|
|
@@ -72457,6 +72822,38 @@ var LockControlStatusSchema = object({
|
|
|
72457
72822
|
/** Ms epoch when the slice was last updated. */
|
|
72458
72823
|
lastChangedAt: number()
|
|
72459
72824
|
});
|
|
72825
|
+
/**
|
|
72826
|
+
* "Door contact" Customize extension (D984): the ONE extension that replaces a
|
|
72827
|
+
* native field. `state` is listed in `overridable` for this target, so the
|
|
72828
|
+
* validator and the guard accept it and nothing else.
|
|
72829
|
+
*/
|
|
72830
|
+
var lockControlCustomize = {
|
|
72831
|
+
version: 1,
|
|
72832
|
+
overridable: [{
|
|
72833
|
+
path: "state",
|
|
72834
|
+
by: "door-contact"
|
|
72835
|
+
}],
|
|
72836
|
+
targets: [{
|
|
72837
|
+
id: "door-contact",
|
|
72838
|
+
cardinality: "scalar",
|
|
72839
|
+
vocabulary: {
|
|
72840
|
+
cap: "lock-control",
|
|
72841
|
+
stateField: "state"
|
|
72842
|
+
},
|
|
72843
|
+
deviceTypes: [DeviceType.Lock],
|
|
72844
|
+
apply: "replace",
|
|
72845
|
+
path: "state",
|
|
72846
|
+
override: {
|
|
72847
|
+
whenSourceTrue: "door-open",
|
|
72848
|
+
unlessNative: ["jammed"]
|
|
72849
|
+
},
|
|
72850
|
+
sources: [{
|
|
72851
|
+
kind: "binary",
|
|
72852
|
+
transforms: [{ kind: "identity" }]
|
|
72853
|
+
}],
|
|
72854
|
+
sourceReport: { status: "assignment-status" }
|
|
72855
|
+
}]
|
|
72856
|
+
};
|
|
72460
72857
|
var lockControlCapability = {
|
|
72461
72858
|
name: "lock-control",
|
|
72462
72859
|
scope: "device",
|
|
@@ -72502,6 +72899,7 @@ var lockControlCapability = {
|
|
|
72502
72899
|
* transitions.
|
|
72503
72900
|
*/
|
|
72504
72901
|
runtimeState: LockControlStatusSchema,
|
|
72902
|
+
customize: lockControlCustomize,
|
|
72505
72903
|
/**
|
|
72506
72904
|
* Runtime-state durability: **restored** — a lock left locked must still read locked.
|
|
72507
72905
|
*
|
|
@@ -81016,7 +81414,6 @@ discriminatedUnion("kind", [object({
|
|
|
81016
81414
|
})]);
|
|
81017
81415
|
DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
|
|
81018
81416
|
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
81019
|
-
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Gateway, DeviceType.Camera, DeviceType.Camera, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
81020
81417
|
String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
|
|
81021
81418
|
DeviceRole.BinarySensor, DeviceRole.MotionSensor;
|
|
81022
81419
|
new Set(CAP_NAMES);
|
|
@@ -90129,6 +90526,76 @@ Object.freeze({
|
|
|
90129
90526
|
access: "create",
|
|
90130
90527
|
role: "feature:scenes"
|
|
90131
90528
|
},
|
|
90529
|
+
"schedulers.conflicts": {
|
|
90530
|
+
capName: "schedulers",
|
|
90531
|
+
capScope: "system",
|
|
90532
|
+
addonId: null,
|
|
90533
|
+
access: "view",
|
|
90534
|
+
role: "admin"
|
|
90535
|
+
},
|
|
90536
|
+
"schedulers.create": {
|
|
90537
|
+
capName: "schedulers",
|
|
90538
|
+
capScope: "system",
|
|
90539
|
+
addonId: null,
|
|
90540
|
+
access: "create",
|
|
90541
|
+
role: "admin"
|
|
90542
|
+
},
|
|
90543
|
+
"schedulers.delete": {
|
|
90544
|
+
capName: "schedulers",
|
|
90545
|
+
capScope: "system",
|
|
90546
|
+
addonId: null,
|
|
90547
|
+
access: "delete",
|
|
90548
|
+
role: "admin"
|
|
90549
|
+
},
|
|
90550
|
+
"schedulers.get": {
|
|
90551
|
+
capName: "schedulers",
|
|
90552
|
+
capScope: "system",
|
|
90553
|
+
addonId: null,
|
|
90554
|
+
access: "view",
|
|
90555
|
+
role: "admin"
|
|
90556
|
+
},
|
|
90557
|
+
"schedulers.getStatus": {
|
|
90558
|
+
capName: "schedulers",
|
|
90559
|
+
capScope: "system",
|
|
90560
|
+
addonId: null,
|
|
90561
|
+
access: "view",
|
|
90562
|
+
role: "admin"
|
|
90563
|
+
},
|
|
90564
|
+
"schedulers.getTraces": {
|
|
90565
|
+
capName: "schedulers",
|
|
90566
|
+
capScope: "system",
|
|
90567
|
+
addonId: null,
|
|
90568
|
+
access: "view",
|
|
90569
|
+
role: "admin"
|
|
90570
|
+
},
|
|
90571
|
+
"schedulers.list": {
|
|
90572
|
+
capName: "schedulers",
|
|
90573
|
+
capScope: "system",
|
|
90574
|
+
addonId: null,
|
|
90575
|
+
access: "view",
|
|
90576
|
+
role: "admin"
|
|
90577
|
+
},
|
|
90578
|
+
"schedulers.preview": {
|
|
90579
|
+
capName: "schedulers",
|
|
90580
|
+
capScope: "system",
|
|
90581
|
+
addonId: null,
|
|
90582
|
+
access: "view",
|
|
90583
|
+
role: "admin"
|
|
90584
|
+
},
|
|
90585
|
+
"schedulers.setEnabled": {
|
|
90586
|
+
capName: "schedulers",
|
|
90587
|
+
capScope: "system",
|
|
90588
|
+
addonId: null,
|
|
90589
|
+
access: "create",
|
|
90590
|
+
role: "admin"
|
|
90591
|
+
},
|
|
90592
|
+
"schedulers.update": {
|
|
90593
|
+
capName: "schedulers",
|
|
90594
|
+
capScope: "system",
|
|
90595
|
+
addonId: null,
|
|
90596
|
+
access: "create",
|
|
90597
|
+
role: "admin"
|
|
90598
|
+
},
|
|
90132
90599
|
"scriptRunner.getStatus": {
|
|
90133
90600
|
capName: "script-runner",
|
|
90134
90601
|
capScope: "device",
|
|
@@ -98714,6 +99181,7 @@ new Set([
|
|
|
98714
99181
|
"locking",
|
|
98715
99182
|
"unlocking",
|
|
98716
99183
|
"jammed",
|
|
99184
|
+
"door-open",
|
|
98717
99185
|
"on",
|
|
98718
99186
|
"off",
|
|
98719
99187
|
"home",
|