@camstack/addon-pipeline-orchestrator 1.2.645 → 1.2.646

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/index.js CHANGED
@@ -5619,7 +5619,7 @@ var ZodIssueCode = {
5619
5619
  var ZodFirstPartyTypeKind;
5620
5620
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5621
5621
  //#endregion
5622
- //#region ../types/dist/sleep-CeyhrcOk.mjs
5622
+ //#region ../types/dist/sleep-DSVWZfJC.mjs
5623
5623
  /**
5624
5624
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5625
5625
  * window to float samples (D455).
@@ -7338,6 +7338,26 @@ var BaseAddon = class {
7338
7338
  * alternative — skip it — turns a rename into a surface that quietly
7339
7339
  * empties, which looks exactly like an addon with nothing to configure.
7340
7340
  */
7341
+ /**
7342
+ * The form schema of ONE integration instance, or `null` to use {@link globalSettingsSchema}.
7343
+ *
7344
+ * Override it only when an `instanceMode: multiple` addon's instances differ: an NVR integration
7345
+ * needs its connection fields, the default integration the addon's own sections. It is the
7346
+ * SHAPE of the form only — the values live in `integrations.getSettings`, and the write path is
7347
+ * unchanged (`integrations.setSettings` for an account integration).
7348
+ */
7349
+ async integrationSettingsSchema(_instance) {
7350
+ return null;
7351
+ }
7352
+ /**
7353
+ * What the create wizard and the integration edit page render for one instance: the addon's
7354
+ * per-instance schema when it declares one, else its global schema (what they always showed).
7355
+ */
7356
+ async getIntegrationFormSchema(instance, nodeId) {
7357
+ const scoped = await this.integrationSettingsSchema(instance);
7358
+ if (scoped === null) return this.getGlobalSettings(void 0, void 0, nodeId);
7359
+ return hydrateSchema(scoped, {}, { inlineSecretsAsViews: true });
7360
+ }
7341
7361
  async getIntegrationSettings(nodeId) {
7342
7362
  const declared = this.integrationSettingSections();
7343
7363
  if (declared.length === 0) return null;
@@ -9776,6 +9796,7 @@ var CAP_NAMES = Object.freeze([
9776
9796
  "remote-layout-components",
9777
9797
  "running-state",
9778
9798
  "scene-monitor",
9799
+ "schedulers",
9779
9800
  "script-runner",
9780
9801
  "server-management",
9781
9802
  "settings-store",
@@ -10721,7 +10742,8 @@ Object.freeze({
10721
10742
  "unlocked",
10722
10743
  "locking",
10723
10744
  "unlocking",
10724
- "jammed"
10745
+ "jammed",
10746
+ "door-open"
10725
10747
  ]
10726
10748
  }],
10727
10749
  "media-player": [
@@ -13401,6 +13423,25 @@ var EventOwnerTypeSchema = _enum(EVENT_OWNER_TYPES);
13401
13423
  /** The same list as a Zod enum, for the cap input that carries it. */
13402
13424
  var MediaPresenceOwnerKindSchema = _enum([...EVENT_OWNER_TYPES, "track"]);
13403
13425
  new Set(EVENT_OWNER_TYPES);
13426
+ /**
13427
+ * Which integration instance a settings form is for. An addon that serves several instances
13428
+ * (`instanceMode: multiple`) can show a different form per instance — an NVR integration
13429
+ * needs its connection, the default integration needs the addon's own sections.
13430
+ *
13431
+ * - `integrationId` is `null` in the create wizard: nothing exists yet, the operator is
13432
+ * setting up a NEW instance.
13433
+ * - `mode` is the wizard mode of the integration type (`getAvailableTypes`).
13434
+ * - `candidateStableId` is the discovery candidate a wizard was seeded from, if any.
13435
+ */
13436
+ var IntegrationInstanceRefSchema = object({
13437
+ integrationId: string().nullable(),
13438
+ mode: _enum([
13439
+ "standalone",
13440
+ "account",
13441
+ "broker"
13442
+ ]),
13443
+ candidateStableId: string().optional()
13444
+ });
13404
13445
  var EncodeProfileSchema = object({
13405
13446
  video: object({
13406
13447
  codec: _enum([
@@ -17652,6 +17693,11 @@ var ACTUATOR_CAP_VOCABULARY = {
17652
17693
  value: "jammed",
17653
17694
  label: t("Jammed", "Inceppata"),
17654
17695
  phrase: t("When {device} jams", "Quando {device} si inceppa")
17696
+ },
17697
+ {
17698
+ value: "door-open",
17699
+ label: t("Door open", "Porta aperta"),
17700
+ phrase: t("When the door of {device} opens", "Quando la porta di {device} si apre")
17655
17701
  }
17656
17702
  ],
17657
17703
  icon: "lock"
@@ -21142,6 +21188,7 @@ var SYSTEM_CAP_VOCABULARY = {
21142
21188
  records: system(INTERNAL),
21143
21189
  remote: system("the per-device remote setup — authored in the Customize remote editor, sent through the remote UI"),
21144
21190
  "remote-layout-components": system("the palette of the remote template editor — read-only data, never actuated"),
21191
+ schedulers: system("time schedulers — authored on their own page, not device actions"),
21145
21192
  "server-management": system(CLUSTER),
21146
21193
  "settings-store": system(INTERNAL),
21147
21194
  "smtp-provider": system(INTERNAL),
@@ -42005,6 +42052,122 @@ var AutomationWhenSchema = lazy(() => discriminatedUnion("kind", [
42005
42052
  StationaryPresentLeafSchema,
42006
42053
  ExpressionLeafSchema
42007
42054
  ]));
42055
+ var EVENT_KINDS = new Set([
42056
+ "device-becomes",
42057
+ "device-event",
42058
+ "schedule",
42059
+ "manual",
42060
+ "interval",
42061
+ "detection",
42062
+ "stationary"
42063
+ ]);
42064
+ function isEventLeaf(node) {
42065
+ return EVENT_KINDS.has(node.kind);
42066
+ }
42067
+ function isLeaf(node) {
42068
+ return node.kind !== "all" && node.kind !== "any" && node.kind !== "not";
42069
+ }
42070
+ /** Depth of a tree, root container = 1. A bare leaf is depth 1. */
42071
+ function whenDepth(node) {
42072
+ if (isLeaf(node)) return 1;
42073
+ if (node.kind === "not") return 1 + whenDepth(node.child);
42074
+ let deepest = 0;
42075
+ for (const child of node.children) deepest = Math.max(deepest, whenDepth(child));
42076
+ return 1 + deepest;
42077
+ }
42078
+ /** Leaves only — containers do not count toward the leaf budget. */
42079
+ function countWhenLeaves(node) {
42080
+ if (isLeaf(node)) return 1;
42081
+ if (node.kind === "not") return countWhenLeaves(node.child);
42082
+ let total = 0;
42083
+ for (const child of node.children) total += countWhenLeaves(child);
42084
+ return total;
42085
+ }
42086
+ /** Every leaf with its path (`when`, `when.0`, `when.0.1`, `when.0` under a `not`). */
42087
+ function forEachLeaf(node, visit, path = "when") {
42088
+ if (isLeaf(node)) {
42089
+ visit(node, path);
42090
+ return;
42091
+ }
42092
+ if (node.kind === "not") {
42093
+ forEachLeaf(node.child, visit, `${path}.0`);
42094
+ return;
42095
+ }
42096
+ node.children.forEach((child, i) => {
42097
+ forEachLeaf(child, visit, `${path}.${i}`);
42098
+ });
42099
+ }
42100
+ function hasEventLeaves(node) {
42101
+ let found = false;
42102
+ forEachLeaf(node, (leaf) => {
42103
+ if (isEventLeaf(leaf)) found = true;
42104
+ });
42105
+ return found;
42106
+ }
42107
+ function hasEmptyContainer(node) {
42108
+ if (isLeaf(node)) return false;
42109
+ if (node.kind === "not") return hasEmptyContainer(node.child);
42110
+ if (node.children.length === 0) return true;
42111
+ return node.children.some(hasEmptyContainer);
42112
+ }
42113
+ var LEAF_WORDS = {
42114
+ "device-becomes": "a device value that becomes",
42115
+ "device-event": "a device event",
42116
+ schedule: "a schedule",
42117
+ manual: "a manual run",
42118
+ interval: "an interval",
42119
+ detection: "a detection",
42120
+ stationary: "a parked object appearing or leaving"
42121
+ };
42122
+ function say(kind) {
42123
+ return LEAF_WORDS[kind] ?? kind;
42124
+ }
42125
+ /**
42126
+ * The cheapest set of event leaves that makes `node` true, with negation pushed
42127
+ * down to the leaves first (De Morgan), so `not(any(A, B))` and `all(not A,
42128
+ * not B)` are the same shape to the check. A negated event is its own error: an
42129
+ * event is an instant, "the event did not occur" is true at every other moment.
42130
+ */
42131
+ function eventNeed(node, path, negated) {
42132
+ if (isLeaf(node)) {
42133
+ if (!isEventLeaf(node)) return { paths: [] };
42134
+ 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"` };
42135
+ return { paths: [{
42136
+ path,
42137
+ kind: node.kind
42138
+ }] };
42139
+ }
42140
+ if (node.kind === "not") return eventNeed(node.child, `${path}.0`, !negated);
42141
+ const conjunctive = node.kind === "all" !== negated;
42142
+ const parts = [];
42143
+ for (let i = 0; i < node.children.length; i += 1) {
42144
+ const child = node.children[i];
42145
+ if (child === void 0) continue;
42146
+ const need = eventNeed(child, `${path}.${i}`, negated);
42147
+ if ("error" in need) return need;
42148
+ parts.push(need);
42149
+ }
42150
+ if (conjunctive) return { paths: parts.flatMap((p) => p.paths) };
42151
+ let best;
42152
+ for (const part of parts) if (best === void 0 || part.paths.length < best.paths.length) best = part;
42153
+ return best ?? { paths: [] };
42154
+ }
42155
+ /**
42156
+ * Author-time bounds and sense check of a `when` tree. Returns `null` when it
42157
+ * is legal, else a message the editor shows verbatim.
42158
+ */
42159
+ function validateWhenTree(when) {
42160
+ if (hasEmptyContainer(when)) return "a group is empty — group existing rows instead of leaving a container to fill";
42161
+ const depth = whenDepth(when);
42162
+ 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`;
42163
+ const leaves = countWhenLeaves(when);
42164
+ if (leaves > 32) return `the rules use ${leaves} rows — the limit is 32`;
42165
+ const need = eventNeed(when, "when", false);
42166
+ if ("error" in need) return need.error;
42167
+ const [first, second] = need.paths;
42168
+ 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`;
42169
+ return null;
42170
+ }
42008
42171
  /**
42009
42172
  * The recipe shape before the single `when` tree: a flat list of triggers
42010
42173
  * (OR'd, each an instant) and an optional condition tree. Stored recipes —
@@ -42360,6 +42523,187 @@ function convertLegacyRecipe(legacy) {
42360
42523
  var AutomationRecipeSchema = union([CurrentAutomationRecipeSchema, LegacyAutomationRecipeSchema.transform(convertLegacyRecipe)]);
42361
42524
  new Set(Object.values(COCO_TO_MACRO.mapping));
42362
42525
  /**
42526
+ * Schedulers (D983) — an entity that performs actions over the day.
42527
+ *
42528
+ * A scheduler has profiles; a profile has weekdays and a timeline of POINTS.
42529
+ * A point is an `edge` (run once at its time), a `hold` (from this point until
42530
+ * the next point of the profile, keep the steps' effects true) or a `release`
42531
+ * (end the current hold without acting). The scheduler AND each profile carry
42532
+ * a manual `enabled` flag and an optional `activeWhen`: a `when` STATE tree
42533
+ * (facts only — an event leaf is an instant and cannot be "in force").
42534
+ *
42535
+ * This file is the data half: the schemas, and the author-time rules that
42536
+ * decide whether a scheduler can be saved at all (a hold needs an action that
42537
+ * leads to a state; a sun point needs the site location). It holds no runtime.
42538
+ */
42539
+ /** A `when` tree that is a STATE: no event leaf, and legal as a tree. */
42540
+ var SchedulerStateTreeSchema = AutomationWhenSchema.superRefine((when, ctx) => {
42541
+ if (hasEventLeaves(when)) {
42542
+ ctx.addIssue({
42543
+ code: "custom",
42544
+ message: "a scheduler condition is a state — an event (\"becomes\", \"detects\", \"at a time\") is an instant and cannot be in force"
42545
+ });
42546
+ return;
42547
+ }
42548
+ const problem = validateWhenTree(when);
42549
+ if (problem !== null) ctx.addIssue({
42550
+ code: "custom",
42551
+ message: problem
42552
+ });
42553
+ });
42554
+ /** A point's moment: a clock time or a sun event. A one-shot date is not a position on a day. */
42555
+ 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" });
42556
+ var SchedulerPointModeSchema = _enum([
42557
+ "edge",
42558
+ "hold",
42559
+ "release"
42560
+ ]);
42561
+ /** What a hold does when someone changes the device by hand. */
42562
+ var HoldOverrideSchema = discriminatedUnion("mode", [object({ mode: literal("respect") }), object({
42563
+ mode: literal("reassert"),
42564
+ /** How long the manual state is left alone before the hold puts its own back. */
42565
+ graceMs: number().int().min(0).max(24 * 36e5)
42566
+ })]);
42567
+ /** A missed edge up to this late still runs. */
42568
+ var DEFAULT_MAX_LATE_MS = 10 * 6e4;
42569
+ var SchedulerPointSchema = object({
42570
+ id: string().min(1).max(64),
42571
+ at: SchedulerTimeSpecSchema,
42572
+ mode: SchedulerPointModeSchema,
42573
+ /** The actions of an `edge` or `hold`; a `release` has none. */
42574
+ steps: array(ActionStepSchema).max(20).default([]),
42575
+ /** Checked when the point runs (an edge) or is applied (a hold). */
42576
+ conditions: SchedulerStateTreeSchema.optional(),
42577
+ /** Hold only; absent means `respect`. */
42578
+ override: HoldOverrideSchema.optional(),
42579
+ /** Hold only: re-applications per window; absent means {@link DEFAULT_MAX_HOLD_ATTEMPTS}. */
42580
+ maxHoldAttempts: number().int().min(1).max(20).optional()
42581
+ });
42582
+ var SchedulerProfileSchema = object({
42583
+ id: string().min(1).max(64),
42584
+ name: string().min(1).max(120),
42585
+ enabled: boolean().default(true),
42586
+ activeWhen: SchedulerStateTreeSchema.optional(),
42587
+ days: array(WeekdayKeySchema).min(1).max(7),
42588
+ points: array(SchedulerPointSchema).max(50)
42589
+ });
42590
+ /** What an operator writes. */
42591
+ var SchedulerInputSchema = object({
42592
+ name: string().min(1).max(120),
42593
+ enabled: boolean().default(true),
42594
+ activeWhen: SchedulerStateTreeSchema.optional(),
42595
+ /** Higher wins when two holds want the same device in different states. */
42596
+ priority: number().int().min(0).max(100).default(0),
42597
+ maxLateMs: number().int().min(1e3).max(24 * 36e5).default(DEFAULT_MAX_LATE_MS),
42598
+ profiles: array(SchedulerProfileSchema).max(20)
42599
+ });
42600
+ var SchedulerSchema = SchedulerInputSchema.extend({
42601
+ id: string().min(1),
42602
+ createdAt: number(),
42603
+ updatedAt: number()
42604
+ });
42605
+ /** Every outcome a scheduler reports to the runs ledger (`AutomationRunTrace.scheduler`). */
42606
+ var SchedulerOutcomeSchema = _enum([
42607
+ "done",
42608
+ "missed",
42609
+ "inactive",
42610
+ "condition-false",
42611
+ "failed",
42612
+ "held",
42613
+ "gave-up",
42614
+ "overridden",
42615
+ "suspended-manual"
42616
+ ]);
42617
+ _enum([
42618
+ "not-found",
42619
+ "invalid-scheduler",
42620
+ "invalid-date"
42621
+ ]);
42622
+ var LOCAL_DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
42623
+ /** One point of the day, placed. `at` is `null` when the sun never crosses that day. */
42624
+ var SchedulerPreviewPointSchema = object({
42625
+ pointId: string(),
42626
+ mode: SchedulerPointModeSchema,
42627
+ at: number().nullable(),
42628
+ /** A hold: when its window ends (the next point, else the end of the day). */
42629
+ until: number().nullable(),
42630
+ /** The point's steps are held on a different scheduler's claim at this time — see `conflicts`. */
42631
+ stepCount: number().int()
42632
+ });
42633
+ var SchedulerPreviewSchema = object({
42634
+ schedulerId: string(),
42635
+ /** The site-local day previewed. */
42636
+ date: string().regex(LOCAL_DATE_PATTERN),
42637
+ timeZone: string(),
42638
+ /** Why no profile is in force, or `null` when one is. */
42639
+ idleReason: string().nullable(),
42640
+ /** The profile in force that day: first in list order whose rules hold. */
42641
+ profileId: string().nullable(),
42642
+ points: array(SchedulerPreviewPointSchema)
42643
+ });
42644
+ /** Two holds that want the same device in different states at the same time. */
42645
+ var SchedulerConflictSchema = object({
42646
+ deviceId: number().int(),
42647
+ cap: string(),
42648
+ field: string(),
42649
+ mine: object({
42650
+ profileId: string(),
42651
+ pointId: string(),
42652
+ value: union([
42653
+ string(),
42654
+ number(),
42655
+ boolean()
42656
+ ]),
42657
+ priority: number().int()
42658
+ }),
42659
+ other: object({
42660
+ schedulerId: string(),
42661
+ schedulerName: string(),
42662
+ profileId: string(),
42663
+ pointId: string(),
42664
+ value: union([
42665
+ string(),
42666
+ number(),
42667
+ boolean()
42668
+ ]),
42669
+ priority: number().int()
42670
+ }),
42671
+ /** The overlapping stretch, as site-local minutes of the day. */
42672
+ fromMinute: number().int(),
42673
+ toMinute: number().int(),
42674
+ /** `mine` | `other` | `tie` — who holds when it happens (a tie: the one that started first). */
42675
+ winner: _enum([
42676
+ "mine",
42677
+ "other",
42678
+ "tie"
42679
+ ])
42680
+ });
42681
+ var HoldTargetStatusSchema = _enum([
42682
+ "pending",
42683
+ "held",
42684
+ "suspended-manual",
42685
+ "gave-up",
42686
+ "overridden"
42687
+ ]);
42688
+ var SchedulerStatusSchema = object({
42689
+ schedulerId: string(),
42690
+ profileId: string().nullable(),
42691
+ /** The hold in force right now, with where each target stands. */
42692
+ hold: object({
42693
+ pointId: string(),
42694
+ until: number(),
42695
+ /** `true` while the scheduler or profile `activeWhen` is false. */
42696
+ suspendedInactive: boolean(),
42697
+ targets: array(object({
42698
+ deviceId: number().int(),
42699
+ cap: string(),
42700
+ field: string(),
42701
+ status: HoldTargetStatusSchema,
42702
+ attempts: number().int()
42703
+ }))
42704
+ }).nullable()
42705
+ });
42706
+ /**
42363
42707
  * Run traces — what an automation (or, later, an Action run) DID, node by node,
42364
42708
  * so the editor can paint every block green or red with its reason.
42365
42709
  *
@@ -42495,7 +42839,13 @@ var AutomationRunTraceSchema = object({
42495
42839
  /** How many identical consecutive skips this trace stands for (>= 1). */
42496
42840
  repeat: number().int().min(1),
42497
42841
  /** When the latest of those repeats happened. */
42498
- lastAt: number()
42842
+ lastAt: number(),
42843
+ /**
42844
+ * A scheduler point's own outcome (D983). `outcome` carries the closest
42845
+ * automation outcome so a reader that does not know schedulers still reads
42846
+ * the trace; this field says exactly what happened.
42847
+ */
42848
+ scheduler: SchedulerOutcomeSchema.optional()
42499
42849
  });
42500
42850
  /**
42501
42851
  * What the hub's `runs` ledger holds for one owner (`automation:<blockId>` or
@@ -43224,6 +43574,10 @@ method(object({
43224
43574
  }), method(object({
43225
43575
  addonId: string(),
43226
43576
  nodeId: string().optional()
43577
+ }), SettingsSchemaWithValuesSchema.nullable()), method(object({
43578
+ addonId: string(),
43579
+ nodeId: string().optional(),
43580
+ instance: IntegrationInstanceRefSchema
43227
43581
  }), SettingsSchemaWithValuesSchema.nullable()), method(object({
43228
43582
  addonId: string(),
43229
43583
  nodeId: string().optional()
@@ -45942,6 +46296,7 @@ method(object({
45942
46296
  kind: "mutation",
45943
46297
  auth: "admin"
45944
46298
  }), method(object({ blockIds: array(string()) }), object({ states: array(CompositionBlockStateSchema) }), { auth: "admin" });
46299
+ 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;
45945
46300
  var NUMBER = {
45946
46301
  kind: "fixed",
45947
46302
  result: ["number"]
@@ -65589,6 +65944,43 @@ method(object({}), array(ActionEntrySchema), { auth: "admin" }), method(object({
65589
65944
  auth: "admin"
65590
65945
  });
65591
65946
  /**
65947
+ * schedulers — timelines of edge and hold points that perform actions over the
65948
+ * day (D983). Provided by the core-blocks builtin on the hub, beside `actions`:
65949
+ * the same runs ledger (owner `scheduler:<id>`), the same target resolver, the
65950
+ * same step runner.
65951
+ *
65952
+ * The hub runs ONE timer for the next point across every scheduler. A save is
65953
+ * refused with its reason (`[invalid-scheduler] …`) when a hold has a step that
65954
+ * leads to no state, or a sun point has no site location to read.
65955
+ */
65956
+ var SchedulerIdInput = object({ schedulerId: string().min(1) });
65957
+ method(object({}), array(SchedulerSchema), { auth: "admin" }), method(SchedulerIdInput, object({ scheduler: SchedulerSchema.nullable() }), { auth: "admin" }), method(object({ scheduler: SchedulerInputSchema }), object({ scheduler: SchedulerSchema }), {
65958
+ kind: "mutation",
65959
+ auth: "admin"
65960
+ }), method(object({
65961
+ schedulerId: string().min(1),
65962
+ scheduler: SchedulerInputSchema
65963
+ }), object({ scheduler: SchedulerSchema }), {
65964
+ kind: "mutation",
65965
+ auth: "admin"
65966
+ }), method(SchedulerIdInput, _void(), {
65967
+ kind: "mutation",
65968
+ auth: "admin"
65969
+ }), method(object({
65970
+ schedulerId: string().min(1),
65971
+ profileId: string().min(1).optional(),
65972
+ enabled: boolean()
65973
+ }), object({ scheduler: SchedulerSchema }), {
65974
+ kind: "mutation",
65975
+ auth: "admin"
65976
+ }), method(object({
65977
+ schedulerId: string().min(1),
65978
+ date: string().regex(LOCAL_DATE_PATTERN).optional()
65979
+ }), SchedulerPreviewSchema, { auth: "admin" }), method(object({
65980
+ scheduler: SchedulerInputSchema,
65981
+ schedulerId: string().min(1).optional()
65982
+ }), object({ conflicts: array(SchedulerConflictSchema) }), { auth: "admin" }), method(object({}), array(SchedulerStatusSchema), { auth: "admin" }), method(SchedulerIdInput, object({ traces: array(AutomationRunTraceSchema) }), { auth: "admin" });
65983
+ /**
65592
65984
  * actions — the ONE surface for runnable actions, for the UI and for
65593
65985
  * automations. Provided by the core-blocks builtin on the hub.
65594
65986
  *
@@ -68343,6 +68735,8 @@ var IntegrationWithStateSchema = object({
68343
68735
  name: string(),
68344
68736
  enabled: boolean(),
68345
68737
  info: record(string(), unknown()).readonly(),
68738
+ /** The discovery candidate this integration was set up from (D984). */
68739
+ originStableId: string().optional(),
68346
68740
  createdAt: number(),
68347
68741
  updatedAt: number(),
68348
68742
  processState: string()
@@ -68353,6 +68747,8 @@ var IntegrationLiteSchema = object({
68353
68747
  name: string(),
68354
68748
  enabled: boolean(),
68355
68749
  info: record(string(), unknown()).readonly(),
68750
+ /** The discovery candidate this integration was set up from (D984). */
68751
+ originStableId: string().optional(),
68356
68752
  createdAt: number(),
68357
68753
  updatedAt: number()
68358
68754
  });
@@ -68450,6 +68846,8 @@ var CreateIntegrationInputSchema = object({
68450
68846
  name: string(),
68451
68847
  enabled: boolean().optional(),
68452
68848
  info: record(string(), unknown()).optional(),
68849
+ /** `stableId` of the discovery candidate the form was seeded from (D984). */
68850
+ originStableId: string().optional(),
68453
68851
  settings: record(string(), unknown()).optional(),
68454
68852
  /** Keys of `settings` the form's schema declares secret (by type) — kept in
68455
68853
  * the keychain, not the table (D787). */
@@ -69067,11 +69465,13 @@ object({
69067
69465
  "unlocked",
69068
69466
  "locking",
69069
69467
  "unlocking",
69070
- "jammed"
69468
+ "jammed",
69469
+ "door-open"
69071
69470
  ]),
69072
69471
  /** Ms epoch when the slice was last updated. */
69073
69472
  lastChangedAt: number()
69074
69473
  });
69474
+ DeviceType.Lock;
69075
69475
  DeviceType.Lock, method(object({
69076
69476
  deviceId: number().int().nonnegative(),
69077
69477
  /** Optional PIN code required by some keypad locks. NOT
@@ -76296,7 +76696,6 @@ discriminatedUnion("kind", [object({
76296
76696
  })]);
76297
76697
  DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
76298
76698
  SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
76299
- 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;
76300
76699
  String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
76301
76700
  DeviceRole.BinarySensor, DeviceRole.MotionSensor;
76302
76701
  new Set(CAP_NAMES);
@@ -76758,6 +77157,13 @@ Object.freeze({
76758
77157
  access: "view",
76759
77158
  role: "admin"
76760
77159
  },
77160
+ "addonSettings.getIntegrationFormSchema": {
77161
+ capName: "addon-settings",
77162
+ capScope: "system",
77163
+ addonId: null,
77164
+ access: "view",
77165
+ role: "admin"
77166
+ },
76761
77167
  "addonSettings.getIntegrationSettings": {
76762
77168
  capName: "addon-settings",
76763
77169
  capScope: "system",
@@ -84290,6 +84696,76 @@ Object.freeze({
84290
84696
  access: "create",
84291
84697
  role: "feature:scenes"
84292
84698
  },
84699
+ "schedulers.conflicts": {
84700
+ capName: "schedulers",
84701
+ capScope: "system",
84702
+ addonId: null,
84703
+ access: "view",
84704
+ role: "admin"
84705
+ },
84706
+ "schedulers.create": {
84707
+ capName: "schedulers",
84708
+ capScope: "system",
84709
+ addonId: null,
84710
+ access: "create",
84711
+ role: "admin"
84712
+ },
84713
+ "schedulers.delete": {
84714
+ capName: "schedulers",
84715
+ capScope: "system",
84716
+ addonId: null,
84717
+ access: "delete",
84718
+ role: "admin"
84719
+ },
84720
+ "schedulers.get": {
84721
+ capName: "schedulers",
84722
+ capScope: "system",
84723
+ addonId: null,
84724
+ access: "view",
84725
+ role: "admin"
84726
+ },
84727
+ "schedulers.getStatus": {
84728
+ capName: "schedulers",
84729
+ capScope: "system",
84730
+ addonId: null,
84731
+ access: "view",
84732
+ role: "admin"
84733
+ },
84734
+ "schedulers.getTraces": {
84735
+ capName: "schedulers",
84736
+ capScope: "system",
84737
+ addonId: null,
84738
+ access: "view",
84739
+ role: "admin"
84740
+ },
84741
+ "schedulers.list": {
84742
+ capName: "schedulers",
84743
+ capScope: "system",
84744
+ addonId: null,
84745
+ access: "view",
84746
+ role: "admin"
84747
+ },
84748
+ "schedulers.preview": {
84749
+ capName: "schedulers",
84750
+ capScope: "system",
84751
+ addonId: null,
84752
+ access: "view",
84753
+ role: "admin"
84754
+ },
84755
+ "schedulers.setEnabled": {
84756
+ capName: "schedulers",
84757
+ capScope: "system",
84758
+ addonId: null,
84759
+ access: "create",
84760
+ role: "admin"
84761
+ },
84762
+ "schedulers.update": {
84763
+ capName: "schedulers",
84764
+ capScope: "system",
84765
+ addonId: null,
84766
+ access: "create",
84767
+ role: "admin"
84768
+ },
84293
84769
  "scriptRunner.getStatus": {
84294
84770
  capName: "script-runner",
84295
84771
  capScope: "device",
@@ -90347,6 +90823,7 @@ new Set([
90347
90823
  "locking",
90348
90824
  "unlocking",
90349
90825
  "jammed",
90826
+ "door-open",
90350
90827
  "on",
90351
90828
  "off",
90352
90829
  "home",