@camstack/addon-post-analysis 1.2.666 → 1.2.668
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 +18 -0
- package/dist/{clip-model-registry-Uc_C1x81.mjs → clip-model-registry-BYJ5lbPi.mjs} +922 -509
- package/dist/{clip-model-registry-BIhYJRFt.js → clip-model-registry-DTC5bkf8.js} +922 -509
- 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-FkeZoNXj.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-DBEA3TPX.mjs} +2 -2
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DxtNkzmw.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-CU7mDiJp.mjs +26 -0
- package/dist/pipeline-analytics/{hostInit-BBhgVoNl.mjs → hostInit-ChYqK-gn.mjs} +2 -2
- package/dist/pipeline-analytics/index.js +460 -116
- package/dist/pipeline-analytics/index.mjs +460 -116
- package/dist/pipeline-analytics/remoteEntry.js +1 -1
- package/package.json +2 -2
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CnYZAdvw.mjs +0 -26
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-Br6eWzp_.mjs +0 -26
|
@@ -816,7 +816,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
816
816
|
return EventCategory;
|
|
817
817
|
}({});
|
|
818
818
|
//#endregion
|
|
819
|
-
//#region ../types/dist/device-type-
|
|
819
|
+
//#region ../types/dist/device-type-D1fH5kaC.mjs
|
|
820
820
|
/**
|
|
821
821
|
import { errMsg } from '@camstack/types'
|
|
822
822
|
* Extract a human-readable message from an unknown error value.
|
|
@@ -1047,6 +1047,12 @@ var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
|
|
|
1047
1047
|
DeviceFeature["MediaPlayerPrevious"] = "media-player-previous";
|
|
1048
1048
|
/** Media player exposes stop distinct from pause. */
|
|
1049
1049
|
DeviceFeature["MediaPlayerStop"] = "media-player-stop";
|
|
1050
|
+
/** Media player exposes volume up / down in steps (an infrared TV has no level). */
|
|
1051
|
+
DeviceFeature["MediaPlayerVolumeStep"] = "media-player-volume-step";
|
|
1052
|
+
/** Media player exposes channel up / down in steps. */
|
|
1053
|
+
DeviceFeature["MediaPlayerChannelStep"] = "media-player-channel-step";
|
|
1054
|
+
/** Media player exposes power on / off. */
|
|
1055
|
+
DeviceFeature["MediaPlayerPower"] = "media-player-power";
|
|
1050
1056
|
/** Alarm panel requires a PIN code on arm/disarm. */
|
|
1051
1057
|
DeviceFeature["AlarmPinRequired"] = "alarm-pin-required";
|
|
1052
1058
|
/** Presence device carries GPS coordinates (lat/lng/accuracy) in
|
|
@@ -6063,7 +6069,7 @@ var ZodIssueCode = {
|
|
|
6063
6069
|
var ZodFirstPartyTypeKind;
|
|
6064
6070
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
6065
6071
|
//#endregion
|
|
6066
|
-
//#region ../types/dist/sleep-
|
|
6072
|
+
//#region ../types/dist/sleep-D1jjWAr8.mjs
|
|
6067
6073
|
/**
|
|
6068
6074
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
6069
6075
|
* window to float samples (D455).
|
|
@@ -6656,7 +6662,7 @@ var NOT_RUN = {
|
|
|
6656
6662
|
* throws: an unreachable or refusing engine is logged and reported `declared: false`,
|
|
6657
6663
|
* because the hub (and this addon's boot) must not hang on a migration.
|
|
6658
6664
|
*/
|
|
6659
|
-
async function runAddonMigrations(host, migrations, logger) {
|
|
6665
|
+
async function runAddonMigrations(host, migrations, logger, options = {}) {
|
|
6660
6666
|
const first = migrations[0];
|
|
6661
6667
|
if (first === void 0) return NOT_RUN;
|
|
6662
6668
|
const owner = first.meta.owner;
|
|
@@ -6685,7 +6691,9 @@ async function runAddonMigrations(host, migrations, logger) {
|
|
|
6685
6691
|
else if (status === "blocked") blocked.push(id);
|
|
6686
6692
|
else skipped.push(id);
|
|
6687
6693
|
};
|
|
6694
|
+
const selected = options.only === void 0 ? null : new Set(options.only);
|
|
6688
6695
|
for (const step of declaration.steps) {
|
|
6696
|
+
if (selected !== null && !selected.has(step.id)) continue;
|
|
6689
6697
|
const bound = byId.get(step.id);
|
|
6690
6698
|
if (bound === void 0 || step.action === "skip") {
|
|
6691
6699
|
skipped.push(step.id);
|
|
@@ -7803,14 +7811,18 @@ var BaseAddon = class {
|
|
|
7803
7811
|
* nothing; the boot continues. A migration that FAILED (or was blocked by one)
|
|
7804
7812
|
* and declares `onFailure: 'block-owner'` makes this throw, so the addon does not
|
|
7805
7813
|
* serve data whose shape it cannot trust; `tolerate` migrations never do.
|
|
7814
|
+
*
|
|
7815
|
+
* ALWAYS pass the whole catalogue; a phase that must run only some of it passes
|
|
7816
|
+
* `{ only: [ids] }` — never a filtered catalogue (the engine would judge the
|
|
7817
|
+
* omitted applied ids "newer").
|
|
7806
7818
|
*/
|
|
7807
|
-
async runMigrations(migrations) {
|
|
7819
|
+
async runMigrations(migrations, options) {
|
|
7808
7820
|
const api = this.ctx.api.migrations;
|
|
7809
7821
|
const report = await runAddonMigrations({
|
|
7810
7822
|
declareOwner: (input) => api.declareOwner.mutate(input),
|
|
7811
7823
|
startMigration: (input) => api.startMigration.mutate(input),
|
|
7812
7824
|
finishMigration: (input) => api.finishMigration.mutate(input)
|
|
7813
|
-
}, migrations, this.ctx.logger);
|
|
7825
|
+
}, migrations, this.ctx.logger, options);
|
|
7814
7826
|
if (report.blockOwner.length > 0) throw new AddonMigrationsBlockedError(report.blockOwner);
|
|
7815
7827
|
return report;
|
|
7816
7828
|
}
|
|
@@ -8151,6 +8163,10 @@ var BaseAddon = class {
|
|
|
8151
8163
|
const stored = keychain ? await this.readAddonStoreWithRetry() : {};
|
|
8152
8164
|
const patch = {};
|
|
8153
8165
|
for (const key of keys) {
|
|
8166
|
+
if (tree.get(key)?.kind === "array") {
|
|
8167
|
+
patch[key] = [];
|
|
8168
|
+
continue;
|
|
8169
|
+
}
|
|
8154
8170
|
const keychainStored = tree.has(key) || collectSecretMarkerRefs(stored[key]).length > 0;
|
|
8155
8171
|
patch[key] = keychain && keychainStored ? SECRET_CLEAR : "";
|
|
8156
8172
|
}
|
|
@@ -8837,6 +8853,10 @@ var RECORD_SETTINGS_MAX_ROWS = 5e4;
|
|
|
8837
8853
|
* (`collectZodSecretPaths`): dotted keys, `[]` for "each element of this array"
|
|
8838
8854
|
* (`auth.accessToken`, `headers[].value`).
|
|
8839
8855
|
*
|
|
8856
|
+
* `{}` after a key means "each value of this map" (`applianceSecrets{}`): the map's own key
|
|
8857
|
+
* names the value (`applianceSecrets{fridge}`), so no id key is declared and a body that drops a
|
|
8858
|
+
* key releases exactly that key's secret.
|
|
8859
|
+
*
|
|
8840
8860
|
* Array elements are matched by a DECLARED id key (`secretArrayKeys`:
|
|
8841
8861
|
* `{ headers: 'name' }`), never by index, so reordering a list keeps every
|
|
8842
8862
|
* keychain ref (the same rule as `arrayItemFieldPath`). The concrete path of a
|
|
@@ -8849,11 +8869,13 @@ function parseSecretPath(path) {
|
|
|
8849
8869
|
if (path.length === 0) throw new InvalidRecordError("an empty secret path");
|
|
8850
8870
|
return path.split(".").map((raw) => {
|
|
8851
8871
|
const each = raw.endsWith("[]");
|
|
8852
|
-
const
|
|
8872
|
+
const map = raw.endsWith("{}");
|
|
8873
|
+
const key = each || map ? raw.slice(0, -2) : raw;
|
|
8853
8874
|
if (key.length === 0) throw new InvalidRecordError(`secret path "${path}" has an empty segment`);
|
|
8854
8875
|
return {
|
|
8855
8876
|
key,
|
|
8856
|
-
each
|
|
8877
|
+
each,
|
|
8878
|
+
map
|
|
8857
8879
|
};
|
|
8858
8880
|
});
|
|
8859
8881
|
}
|
|
@@ -8940,7 +8962,8 @@ function isZodSecret(schema) {
|
|
|
8940
8962
|
}
|
|
8941
8963
|
/**
|
|
8942
8964
|
* Every declared secret path in a config schema: dotted keys, `[]` for "each
|
|
8943
|
-
* element of this array" (`connection.password`, `rows[].token`)
|
|
8965
|
+
* element of this array" (`connection.password`, `rows[].token`), `{}` for "each value of this
|
|
8966
|
+
* map" (`applianceSecrets{}`). A declared
|
|
8944
8967
|
* object or array is reported as one path and not descended into — everything
|
|
8945
8968
|
* under it is secret.
|
|
8946
8969
|
*/
|
|
@@ -8951,6 +8974,7 @@ function collectZodSecretPaths(schema, prefix = "") {
|
|
|
8951
8974
|
const def = defOf(layer);
|
|
8952
8975
|
if (def.type === "object" && def.shape) for (const [key, child] of Object.entries(def.shape)) paths.push(...collectZodSecretPaths(child, prefix ? `${prefix}.${key}` : key));
|
|
8953
8976
|
else if (def.type === "array" && def.element) paths.push(...collectZodSecretPaths(def.element, `${prefix}[]`));
|
|
8977
|
+
else if (def.type === "record" && def.valueType) paths.push(...collectZodSecretPaths(def.valueType, `${prefix}{}`));
|
|
8954
8978
|
else if (def.type === "union" && def.options) for (const option of def.options) paths.push(...collectZodSecretPaths(option, prefix));
|
|
8955
8979
|
else if (def.type === "intersection") {
|
|
8956
8980
|
if (def.left) paths.push(...collectZodSecretPaths(def.left, prefix));
|
|
@@ -9090,7 +9114,7 @@ function defineRecordKinds(specs) {
|
|
|
9090
9114
|
retention: spec.retention,
|
|
9091
9115
|
deviceRemoval: spec.deviceRemoval,
|
|
9092
9116
|
maxDataBytes: spec.maxDataBytes,
|
|
9093
|
-
secretPaths: [...secretPaths],
|
|
9117
|
+
secretPaths: [...new Set([...secretPaths, ...spec.retiredSecretPaths ?? []])],
|
|
9094
9118
|
secretArrayKeys: spec.secretArrayKeys === void 0 ? void 0 : { ...spec.secretArrayKeys },
|
|
9095
9119
|
transactFamily: spec.transactFamily,
|
|
9096
9120
|
entry: spec.entry === void 0 ? void 0 : {
|
|
@@ -11999,7 +12023,7 @@ function sleep(ms) {
|
|
|
11999
12023
|
return new Promise((resolve) => setTimeout(resolve, Math.max(0, ms)));
|
|
12000
12024
|
}
|
|
12001
12025
|
//#endregion
|
|
12002
|
-
//#region ../types/dist/composition-
|
|
12026
|
+
//#region ../types/dist/composition-pOHbTzRB.mjs
|
|
12003
12027
|
/**
|
|
12004
12028
|
* Deterministic SHA-256 hash of an arbitrary serialisable value. The
|
|
12005
12029
|
* canonical form sorts object keys alphabetically at every depth so two
|
|
@@ -12922,38 +12946,6 @@ function validateExpressionSource(src) {
|
|
|
12922
12946
|
return null;
|
|
12923
12947
|
}
|
|
12924
12948
|
/**
|
|
12925
|
-
* One power reading becomes a washer, dryer or dishwasher (D944 helper).
|
|
12926
|
-
*
|
|
12927
|
-
* Standby of the control board is under 5 W; a motor or a heater is far
|
|
12928
|
-
* above that, so 5 W is the line. A door lock or a short pump spike is not
|
|
12929
|
-
* a cycle, so running starts only after 30 s above the line.
|
|
12930
|
-
*
|
|
12931
|
-
* A wash, dry or dishwasher pause (soak, heat-wait, heater off between
|
|
12932
|
-
* bursts) lasts several minutes. Ending the cycle on the first dip would
|
|
12933
|
-
* report "finished" in the middle of the program, so the stop dwell is
|
|
12934
|
-
* 10 minutes on every type. The number is stored per type so one machine
|
|
12935
|
-
* can move later without moving the others.
|
|
12936
|
-
*/
|
|
12937
|
-
var APPLIANCE_TEMPLATE_ID = "appliance";
|
|
12938
|
-
var APPLIANCE_KINDS = [
|
|
12939
|
-
"washer",
|
|
12940
|
-
"dryer",
|
|
12941
|
-
"dishwasher"
|
|
12942
|
-
];
|
|
12943
|
-
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
|
|
12944
|
-
/**
|
|
12945
|
-
* A dumb plug-in stove or heater, built from a smart plug (a `Heater`).
|
|
12946
|
-
*
|
|
12947
|
-
* The plug is the actuator: `switch.setState` is a FORWARD to the plug's own
|
|
12948
|
-
* (D967), so the heater switches exactly as the plug does. Running is the
|
|
12949
|
-
* plug being on; when a power reading is also named, running is the draw
|
|
12950
|
-
* staying above the line instead (a plug left on with the stove's own
|
|
12951
|
-
* thermostat open is not heating). 50 W is far above any standby and below
|
|
12952
|
-
* the smallest radiator.
|
|
12953
|
-
*/
|
|
12954
|
-
var HEATER_TEMPLATE_ID = "heater";
|
|
12955
|
-
DeviceType.Heater;
|
|
12956
|
-
/**
|
|
12957
12949
|
* Statistics and integrals over a history read (D944).
|
|
12958
12950
|
*
|
|
12959
12951
|
* Pure: the same points always give the same answer, so a restart recomputes
|
|
@@ -13097,34 +13089,6 @@ var HelperSpecSchema = discriminatedUnion("kind", [
|
|
|
13097
13089
|
/** Actuator groups only. Readings leave this unset. */
|
|
13098
13090
|
active: ActiveCriterionSchema.optional()
|
|
13099
13091
|
}),
|
|
13100
|
-
object({
|
|
13101
|
-
kind: literal("appliance"),
|
|
13102
|
-
templateId: literal(APPLIANCE_TEMPLATE_ID),
|
|
13103
|
-
appliance: _enum(APPLIANCE_KINDS),
|
|
13104
|
-
thresholdWatts: number().positive(),
|
|
13105
|
-
startDwellMs: number().int().nonnegative(),
|
|
13106
|
-
stopDwellMs: number().int().nonnegative(),
|
|
13107
|
-
member: HelperMemberSchema,
|
|
13108
|
-
/**
|
|
13109
|
-
* The plug that powers the appliance (`switch.on`). Optional: when set, the
|
|
13110
|
-
* composition carries a `power-source` feature, so the hub can cut and restore
|
|
13111
|
-
* that plug (power-source link of a NEW-target composition).
|
|
13112
|
-
*/
|
|
13113
|
-
powerSwitch: HelperMemberSchema.optional(),
|
|
13114
|
-
/** How long a forced restart keeps the plug off; the cap's default when unset. */
|
|
13115
|
-
offSeconds: number().optional()
|
|
13116
|
-
}),
|
|
13117
|
-
object({
|
|
13118
|
-
kind: literal("heater"),
|
|
13119
|
-
templateId: literal(HEATER_TEMPLATE_ID),
|
|
13120
|
-
/** The plug, read and commanded at `switch.on`. */
|
|
13121
|
-
plug: HelperMemberSchema,
|
|
13122
|
-
/** The plug's power reading, when it has one: running is then the draw, not the switch. */
|
|
13123
|
-
meter: HelperMemberSchema.optional(),
|
|
13124
|
-
thresholdWatts: number().positive(),
|
|
13125
|
-
startDwellMs: number().int().nonnegative(),
|
|
13126
|
-
stopDwellMs: number().int().nonnegative()
|
|
13127
|
-
}),
|
|
13128
13092
|
object({
|
|
13129
13093
|
kind: literal("statistic"),
|
|
13130
13094
|
stat: _enum(STATISTIC_STATS),
|
|
@@ -13296,7 +13260,14 @@ var CompositionForwardCommandSchema = object({
|
|
|
13296
13260
|
method: string().min(1),
|
|
13297
13261
|
args: record(string().min(1), CompositionForwardArgSchema).optional()
|
|
13298
13262
|
});
|
|
13299
|
-
var CompositionCommandTargetSchema = discriminatedUnion("kind", [
|
|
13263
|
+
var CompositionCommandTargetSchema = discriminatedUnion("kind", [
|
|
13264
|
+
CompositionForwardCommandSchema,
|
|
13265
|
+
CompositionCodeSourceSchema,
|
|
13266
|
+
object({
|
|
13267
|
+
kind: literal("extension"),
|
|
13268
|
+
target: literal("remote")
|
|
13269
|
+
})
|
|
13270
|
+
]);
|
|
13300
13271
|
/** An item key inside an item-array cap (`consumables.items[<key>]`). */
|
|
13301
13272
|
var COMPOSITION_ITEM_KEY_RE = /^[a-z0-9][a-z0-9-]{0,47}$/;
|
|
13302
13273
|
/**
|
|
@@ -13341,7 +13312,7 @@ var CompositionSchema = object({
|
|
|
13341
13312
|
kind: literal("existing"),
|
|
13342
13313
|
device: CompositionSourceRefSchema
|
|
13343
13314
|
})]),
|
|
13344
|
-
features: array(CompositionFeatureSchema).min(
|
|
13315
|
+
features: array(CompositionFeatureSchema).min(0).max(16),
|
|
13345
13316
|
/**
|
|
13346
13317
|
* Present when the block is a helper template. Absent on a free
|
|
13347
13318
|
* composition (the room example, device 4603). The editor reads this,
|
|
@@ -14721,7 +14692,13 @@ var MigrationLedgerEntrySchema = object({
|
|
|
14721
14692
|
* joined by the engine from the catalogues it knows this boot. Absent when no
|
|
14722
14693
|
* catalogue lists the id (a newer database).
|
|
14723
14694
|
*/
|
|
14724
|
-
meta: MigrationMetaSchema.optional()
|
|
14695
|
+
meta: MigrationMetaSchema.optional(),
|
|
14696
|
+
/**
|
|
14697
|
+
* Set when this is an applied row of an addon owner whose catalogue the answering
|
|
14698
|
+
* process has not loaded (the owner has not declared yet): the row is applied, the
|
|
14699
|
+
* process just cannot judge it. Never `skipped-newer` — that needs the owner loaded.
|
|
14700
|
+
*/
|
|
14701
|
+
ownerNotLoaded: boolean().optional()
|
|
14725
14702
|
});
|
|
14726
14703
|
/** A catalogued migration that is not applied, with where it stands. */
|
|
14727
14704
|
var MigrationPendingEntrySchema = object({
|
|
@@ -20563,6 +20540,48 @@ var APPLIANCE_CAP_VOCABULARY = {
|
|
|
20563
20540
|
scope: "device",
|
|
20564
20541
|
noun: t("Media player", "Lettore multimediale"),
|
|
20565
20542
|
actions: [
|
|
20543
|
+
{
|
|
20544
|
+
id: "media.turnOn",
|
|
20545
|
+
method: "turnOn",
|
|
20546
|
+
label: t("Turn on", "Accendi"),
|
|
20547
|
+
phrase: t("Turn on {device}", "Accendi {device}"),
|
|
20548
|
+
icon: "power"
|
|
20549
|
+
},
|
|
20550
|
+
{
|
|
20551
|
+
id: "media.turnOff",
|
|
20552
|
+
method: "turnOff",
|
|
20553
|
+
label: t("Turn off", "Spegni"),
|
|
20554
|
+
phrase: t("Turn off {device}", "Spegni {device}"),
|
|
20555
|
+
icon: "power"
|
|
20556
|
+
},
|
|
20557
|
+
{
|
|
20558
|
+
id: "media.volumeUp",
|
|
20559
|
+
method: "volumeUp",
|
|
20560
|
+
label: t("Volume up", "Alza il volume"),
|
|
20561
|
+
phrase: t("Raise the volume of {device}", "Alza il volume di {device}"),
|
|
20562
|
+
icon: "volume-2"
|
|
20563
|
+
},
|
|
20564
|
+
{
|
|
20565
|
+
id: "media.volumeDown",
|
|
20566
|
+
method: "volumeDown",
|
|
20567
|
+
label: t("Volume down", "Abbassa il volume"),
|
|
20568
|
+
phrase: t("Lower the volume of {device}", "Abbassa il volume di {device}"),
|
|
20569
|
+
icon: "volume-2"
|
|
20570
|
+
},
|
|
20571
|
+
{
|
|
20572
|
+
id: "media.channelUp",
|
|
20573
|
+
method: "channelUp",
|
|
20574
|
+
label: t("Channel up", "Canale successivo"),
|
|
20575
|
+
phrase: t("Go to the next channel on {device}", "Passa al canale successivo su {device}"),
|
|
20576
|
+
icon: "skip-forward"
|
|
20577
|
+
},
|
|
20578
|
+
{
|
|
20579
|
+
id: "media.channelDown",
|
|
20580
|
+
method: "channelDown",
|
|
20581
|
+
label: t("Channel down", "Canale precedente"),
|
|
20582
|
+
phrase: t("Go to the previous channel on {device}", "Torna al canale precedente su {device}"),
|
|
20583
|
+
icon: "skip-back"
|
|
20584
|
+
},
|
|
20566
20585
|
{
|
|
20567
20586
|
id: "media.play",
|
|
20568
20587
|
method: "play",
|
|
@@ -50365,6 +50384,244 @@ var controlCapability = {
|
|
|
50365
50384
|
*/
|
|
50366
50385
|
history: "none"
|
|
50367
50386
|
};
|
|
50387
|
+
/**
|
|
50388
|
+
* Media-player cap. Models HA `media_player.*` (Sonos, Chromecast,
|
|
50389
|
+
* Apple TV, Spotify, Roku, generic OTT receivers, …) on
|
|
50390
|
+
* `DeviceType.MediaPlayer`. Disjoint from the camera streaming
|
|
50391
|
+
* surface — those use `DeviceType.Camera` + the broker pipeline.
|
|
50392
|
+
*
|
|
50393
|
+
* The cap declares a wide method surface; not every backend supports
|
|
50394
|
+
* every method. Drivers signal sub-capability via the
|
|
50395
|
+
* `DeviceFeature.MediaPlayerXxx` flags (paired one-to-one with the
|
|
50396
|
+
* corresponding method) so the UI gates buttons without a slice
|
|
50397
|
+
* fetch — same pattern as `PanTiltZoom` for cameras.
|
|
50398
|
+
*/
|
|
50399
|
+
var MediaPlayerStateSchema = _enum([
|
|
50400
|
+
"off",
|
|
50401
|
+
"on",
|
|
50402
|
+
"idle",
|
|
50403
|
+
"playing",
|
|
50404
|
+
"paused",
|
|
50405
|
+
"buffering",
|
|
50406
|
+
"standby"
|
|
50407
|
+
]);
|
|
50408
|
+
var MediaPlayerRepeatSchema = _enum([
|
|
50409
|
+
"off",
|
|
50410
|
+
"all",
|
|
50411
|
+
"one"
|
|
50412
|
+
]);
|
|
50413
|
+
var MediaInfoSchema = object({
|
|
50414
|
+
/** Free-form media kind (`music`, `tvshow`, `movie`, `app`, `channel`,
|
|
50415
|
+
* `podcast`, …). */
|
|
50416
|
+
type: string(),
|
|
50417
|
+
/** Human-readable title. */
|
|
50418
|
+
title: string(),
|
|
50419
|
+
/** Optional artist / channel / station label. */
|
|
50420
|
+
artist: string().optional(),
|
|
50421
|
+
/** Optional album / season / show name. */
|
|
50422
|
+
album: string().optional(),
|
|
50423
|
+
/** Optional cover-art / thumbnail URL. */
|
|
50424
|
+
imageUrl: string().optional()
|
|
50425
|
+
});
|
|
50426
|
+
/**
|
|
50427
|
+
* Where `state`, `volumeLevel`, `isMuted` and `source` come from. `reported`:
|
|
50428
|
+
* the device said so. `assumed`: the driver has no feedback (infrared) and
|
|
50429
|
+
* tracks what it last SENT; it moves only after a send was accepted, and a
|
|
50430
|
+
* human at the real remote makes it wrong. A UI shows an assumed value as a
|
|
50431
|
+
* guess, never as a reading.
|
|
50432
|
+
*/
|
|
50433
|
+
var MediaPlayerStateSourceSchema = _enum(["reported", "assumed"]);
|
|
50434
|
+
/** The fields of a media-player status a driver can only guess. */
|
|
50435
|
+
var MediaPlayerAssumedFieldSchema = _enum([
|
|
50436
|
+
"state",
|
|
50437
|
+
"volumeLevel",
|
|
50438
|
+
"isMuted",
|
|
50439
|
+
"source"
|
|
50440
|
+
]);
|
|
50441
|
+
var MediaPlayerStatusSchema = object({
|
|
50442
|
+
/** Playback lifecycle state. */
|
|
50443
|
+
state: MediaPlayerStateSchema,
|
|
50444
|
+
/**
|
|
50445
|
+
* Whether the state fields are readings or the driver's own bookkeeping.
|
|
50446
|
+
* A slice written before this field existed parses as `reported`.
|
|
50447
|
+
*/
|
|
50448
|
+
stateSource: MediaPlayerStateSourceSchema.default("reported"),
|
|
50449
|
+
/**
|
|
50450
|
+
* Which fields are the driver's own guess. `stateSource` is `assumed` when
|
|
50451
|
+
* this is not empty; a field not listed here is a reading even then (power
|
|
50452
|
+
* from a running-state source, mute guessed from the last send).
|
|
50453
|
+
*/
|
|
50454
|
+
assumedFields: array(MediaPlayerAssumedFieldSchema).default([]),
|
|
50455
|
+
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
50456
|
+
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
50457
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
50458
|
+
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
50459
|
+
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
50460
|
+
isMuted: boolean().nullable(),
|
|
50461
|
+
/** Active source / input. Empty when no source surface. */
|
|
50462
|
+
source: string(),
|
|
50463
|
+
/** Selectable sources. Empty when no source surface.
|
|
50464
|
+
* Pair with `DeviceFeature.MediaPlayerSelectSource`. */
|
|
50465
|
+
availableSources: array(string()),
|
|
50466
|
+
/** Currently-playing media info. Null when nothing is playing. */
|
|
50467
|
+
currentMedia: MediaInfoSchema.nullable(),
|
|
50468
|
+
/** Current playback position in ms. Null when not seekable or
|
|
50469
|
+
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
50470
|
+
position: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
50471
|
+
/** Total duration of the current media in ms. Null when unknown
|
|
50472
|
+
* (live stream) or nothing is playing. */
|
|
50473
|
+
duration: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
50474
|
+
/** Shuffle toggle. Null when no shuffle surface.
|
|
50475
|
+
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
50476
|
+
shuffle: boolean().nullable(),
|
|
50477
|
+
/** Repeat mode. Null when no repeat surface.
|
|
50478
|
+
* Pair with `DeviceFeature.MediaPlayerRepeat`. */
|
|
50479
|
+
repeat: MediaPlayerRepeatSchema.nullable(),
|
|
50480
|
+
/** Ms epoch when the slice was last updated. */
|
|
50481
|
+
lastChangedAt: number()
|
|
50482
|
+
});
|
|
50483
|
+
var stepInput = object({
|
|
50484
|
+
deviceId: number().int().nonnegative(),
|
|
50485
|
+
/** How many presses: the caller's count (Alexa `volumeSteps`, `channelCount`). */
|
|
50486
|
+
steps: number().int().min(1).max(50).default(1)
|
|
50487
|
+
});
|
|
50488
|
+
var deviceOnly = object({ deviceId: number().int().nonnegative() });
|
|
50489
|
+
var mediaPlayerCapability = {
|
|
50490
|
+
name: "media-player",
|
|
50491
|
+
scope: "device",
|
|
50492
|
+
deviceNative: true,
|
|
50493
|
+
mode: "singleton",
|
|
50494
|
+
deviceTypes: [DeviceType.MediaPlayer],
|
|
50495
|
+
methods: {
|
|
50496
|
+
turnOn: method(deviceOnly, _void(), {
|
|
50497
|
+
kind: "mutation",
|
|
50498
|
+
auth: "protected"
|
|
50499
|
+
}),
|
|
50500
|
+
turnOff: method(deviceOnly, _void(), {
|
|
50501
|
+
kind: "mutation",
|
|
50502
|
+
auth: "protected"
|
|
50503
|
+
}),
|
|
50504
|
+
volumeUp: method(stepInput, _void(), {
|
|
50505
|
+
kind: "mutation",
|
|
50506
|
+
auth: "protected"
|
|
50507
|
+
}),
|
|
50508
|
+
volumeDown: method(stepInput, _void(), {
|
|
50509
|
+
kind: "mutation",
|
|
50510
|
+
auth: "protected"
|
|
50511
|
+
}),
|
|
50512
|
+
channelUp: method(stepInput, _void(), {
|
|
50513
|
+
kind: "mutation",
|
|
50514
|
+
auth: "protected"
|
|
50515
|
+
}),
|
|
50516
|
+
channelDown: method(stepInput, _void(), {
|
|
50517
|
+
kind: "mutation",
|
|
50518
|
+
auth: "protected"
|
|
50519
|
+
}),
|
|
50520
|
+
play: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
50521
|
+
kind: "mutation",
|
|
50522
|
+
auth: "protected"
|
|
50523
|
+
}),
|
|
50524
|
+
pause: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
50525
|
+
kind: "mutation",
|
|
50526
|
+
auth: "protected"
|
|
50527
|
+
}),
|
|
50528
|
+
stop: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
50529
|
+
kind: "mutation",
|
|
50530
|
+
auth: "protected"
|
|
50531
|
+
}),
|
|
50532
|
+
next: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
50533
|
+
kind: "mutation",
|
|
50534
|
+
auth: "protected"
|
|
50535
|
+
}),
|
|
50536
|
+
previous: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
50537
|
+
kind: "mutation",
|
|
50538
|
+
auth: "protected"
|
|
50539
|
+
}),
|
|
50540
|
+
seek: method(object({
|
|
50541
|
+
deviceId: number().int().nonnegative(),
|
|
50542
|
+
position: number().int().nonnegative()
|
|
50543
|
+
}), _void(), {
|
|
50544
|
+
kind: "mutation",
|
|
50545
|
+
auth: "protected"
|
|
50546
|
+
}),
|
|
50547
|
+
setVolume: method(object({
|
|
50548
|
+
deviceId: number().int().nonnegative(),
|
|
50549
|
+
volumeLevel: number().min(0).max(100)
|
|
50550
|
+
}), _void(), {
|
|
50551
|
+
kind: "mutation",
|
|
50552
|
+
auth: "protected"
|
|
50553
|
+
}),
|
|
50554
|
+
setMute: method(object({
|
|
50555
|
+
deviceId: number().int().nonnegative(),
|
|
50556
|
+
muted: boolean()
|
|
50557
|
+
}), _void(), {
|
|
50558
|
+
kind: "mutation",
|
|
50559
|
+
auth: "protected"
|
|
50560
|
+
}),
|
|
50561
|
+
setShuffle: method(object({
|
|
50562
|
+
deviceId: number().int().nonnegative(),
|
|
50563
|
+
shuffle: boolean()
|
|
50564
|
+
}), _void(), {
|
|
50565
|
+
kind: "mutation",
|
|
50566
|
+
auth: "protected"
|
|
50567
|
+
}),
|
|
50568
|
+
setRepeat: method(object({
|
|
50569
|
+
deviceId: number().int().nonnegative(),
|
|
50570
|
+
repeat: MediaPlayerRepeatSchema
|
|
50571
|
+
}), _void(), {
|
|
50572
|
+
kind: "mutation",
|
|
50573
|
+
auth: "protected"
|
|
50574
|
+
}),
|
|
50575
|
+
selectSource: method(object({
|
|
50576
|
+
deviceId: number().int().nonnegative(),
|
|
50577
|
+
source: string().min(1)
|
|
50578
|
+
}), _void(), {
|
|
50579
|
+
kind: "mutation",
|
|
50580
|
+
auth: "protected"
|
|
50581
|
+
}),
|
|
50582
|
+
playMedia: method(object({
|
|
50583
|
+
deviceId: number().int().nonnegative(),
|
|
50584
|
+
/** Media identifier / URL. */
|
|
50585
|
+
mediaId: string().min(1),
|
|
50586
|
+
/** Media kind (`music`, `tvshow`, `movie`, `app`, …) — provider
|
|
50587
|
+
* passes it through to the upstream service. */
|
|
50588
|
+
mediaType: string().min(1)
|
|
50589
|
+
}), _void(), {
|
|
50590
|
+
kind: "mutation",
|
|
50591
|
+
auth: "protected"
|
|
50592
|
+
})
|
|
50593
|
+
},
|
|
50594
|
+
status: {
|
|
50595
|
+
schema: MediaPlayerStatusSchema,
|
|
50596
|
+
kind: "push"
|
|
50597
|
+
},
|
|
50598
|
+
/**
|
|
50599
|
+
* Runtime-state slice — mirrored by the kernel. UI players read the
|
|
50600
|
+
* full slice for live now-playing, volume, and progress updates
|
|
50601
|
+
* without polling.
|
|
50602
|
+
*/
|
|
50603
|
+
runtimeState: MediaPlayerStatusSchema,
|
|
50604
|
+
/**
|
|
50605
|
+
* Runtime-state durability: **session** — a restored transport position describes a playback that stopped when the hub did.
|
|
50606
|
+
*
|
|
50607
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
50608
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
50609
|
+
*/
|
|
50610
|
+
durability: "session",
|
|
50611
|
+
/**
|
|
50612
|
+
* History (D850): volume (a level an operator or an automation sets; the
|
|
50613
|
+
* default 10 s floor folds a slider drag into its end value) and mute.
|
|
50614
|
+
* `position` is not recorded: it moves continuously while playing.
|
|
50615
|
+
*/
|
|
50616
|
+
history: { fields: {
|
|
50617
|
+
volumeLevel: {
|
|
50618
|
+
kind: "gauge",
|
|
50619
|
+
unit: "%",
|
|
50620
|
+
deadband: 1
|
|
50621
|
+
},
|
|
50622
|
+
isMuted: { kind: "boolean" }
|
|
50623
|
+
} }
|
|
50624
|
+
};
|
|
50368
50625
|
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.Heater, DeviceType.Dryer, DeviceType.Gateway, DeviceType.Camera, DeviceType.Fan, 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.Heater, 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.Heater, 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.Heater, 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.Heater, DeviceType.Gateway, DeviceType.Hub, DeviceType.Camera, DeviceType.Sensor, DeviceType.MediaPlayer, DeviceType.Vacuum, DeviceType.Generic, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.PetFountain, DeviceType.Fan, DeviceType.Humidifier, DeviceType.Climate, DeviceType.WaterHeater, 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, DeviceType.Heater;
|
|
50369
50626
|
var NUMBER = {
|
|
50370
50627
|
kind: "fixed",
|
|
@@ -50812,117 +51069,6 @@ function actuator(input) {
|
|
|
50812
51069
|
};
|
|
50813
51070
|
}
|
|
50814
51071
|
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
50815
|
-
var PowerSourceRefusalReasonSchema = _enum([
|
|
50816
|
-
"no-power-source",
|
|
50817
|
-
"switch-missing",
|
|
50818
|
-
"switch-offline",
|
|
50819
|
-
"switch-unknown",
|
|
50820
|
-
"restart-in-progress",
|
|
50821
|
-
"switch-call-failed"
|
|
50822
|
-
]);
|
|
50823
|
-
var PowerSourceActionResultSchema = discriminatedUnion("accepted", [object({ accepted: literal(true) }), object({
|
|
50824
|
-
accepted: literal(false),
|
|
50825
|
-
reason: PowerSourceRefusalReasonSchema,
|
|
50826
|
-
/** One line for the operator, naming the switch. */
|
|
50827
|
-
message: string()
|
|
50828
|
-
})]);
|
|
50829
|
-
var PowerSourceInfoSchema = object({
|
|
50830
|
-
/** False when the device has no power source linked; the rest is then empty. */
|
|
50831
|
-
linked: boolean(),
|
|
50832
|
-
switchDeviceId: number().nullable(),
|
|
50833
|
-
switchName: string().nullable(),
|
|
50834
|
-
/** The switch's on/off state, or null when it is unknown. Never false for unknown (D393). */
|
|
50835
|
-
switchOn: boolean().nullable(),
|
|
50836
|
-
switchOnline: boolean().nullable(),
|
|
50837
|
-
restartInProgress: boolean(),
|
|
50838
|
-
offSeconds: number().int()
|
|
50839
|
-
});
|
|
50840
|
-
/** The composed slice: the switch state the link mirrors, plus the stored off time. */
|
|
50841
|
-
var PowerSourceStateSchema = object({
|
|
50842
|
-
/** Null while the switch has not reported: unknown is never `false` (D393). */
|
|
50843
|
-
switchOn: boolean().nullable(),
|
|
50844
|
-
offSeconds: number().int(),
|
|
50845
|
-
lastFetchedAt: number()
|
|
50846
|
-
});
|
|
50847
|
-
var POWER_SOURCE_DEVICE_TYPES = [
|
|
50848
|
-
DeviceType.Gateway,
|
|
50849
|
-
DeviceType.Hub,
|
|
50850
|
-
DeviceType.Camera,
|
|
50851
|
-
DeviceType.Sensor,
|
|
50852
|
-
DeviceType.MediaPlayer,
|
|
50853
|
-
DeviceType.Vacuum,
|
|
50854
|
-
DeviceType.Generic,
|
|
50855
|
-
DeviceType.Washer,
|
|
50856
|
-
DeviceType.Dryer,
|
|
50857
|
-
DeviceType.Dishwasher,
|
|
50858
|
-
DeviceType.PetFountain,
|
|
50859
|
-
DeviceType.Fan,
|
|
50860
|
-
DeviceType.Humidifier,
|
|
50861
|
-
DeviceType.Climate,
|
|
50862
|
-
DeviceType.WaterHeater
|
|
50863
|
-
];
|
|
50864
|
-
var powerSourceCustomize = {
|
|
50865
|
-
version: 1,
|
|
50866
|
-
targets: [{
|
|
50867
|
-
id: "switch",
|
|
50868
|
-
cardinality: "scalar",
|
|
50869
|
-
vocabulary: {
|
|
50870
|
-
cap: "power-source",
|
|
50871
|
-
stateField: "switchOn"
|
|
50872
|
-
},
|
|
50873
|
-
deviceTypes: POWER_SOURCE_DEVICE_TYPES,
|
|
50874
|
-
apply: "add",
|
|
50875
|
-
path: "switchOn",
|
|
50876
|
-
sources: [{
|
|
50877
|
-
kind: "switch",
|
|
50878
|
-
transforms: [{ kind: "identity" }]
|
|
50879
|
-
}],
|
|
50880
|
-
companions: [{
|
|
50881
|
-
kind: "constant",
|
|
50882
|
-
path: "offSeconds",
|
|
50883
|
-
value: 10,
|
|
50884
|
-
when: "add"
|
|
50885
|
-
}, {
|
|
50886
|
-
kind: "clock",
|
|
50887
|
-
path: "lastFetchedAt",
|
|
50888
|
-
when: "always"
|
|
50889
|
-
}],
|
|
50890
|
-
sourceReport: { status: "assignment-status" }
|
|
50891
|
-
}]
|
|
50892
|
-
};
|
|
50893
|
-
var deviceInput$2 = object({ deviceId: number().int().nonnegative() });
|
|
50894
|
-
var powerSourceCapability = {
|
|
50895
|
-
name: "power-source",
|
|
50896
|
-
scope: "device",
|
|
50897
|
-
mode: "singleton",
|
|
50898
|
-
deviceTypes: POWER_SOURCE_DEVICE_TYPES,
|
|
50899
|
-
methods: {
|
|
50900
|
-
getStatus: systemMethod(deviceInput$2, PowerSourceInfoSchema, { auth: "admin" }),
|
|
50901
|
-
powerOn: systemMethod(deviceInput$2, PowerSourceActionResultSchema, {
|
|
50902
|
-
kind: "mutation",
|
|
50903
|
-
auth: "admin"
|
|
50904
|
-
}),
|
|
50905
|
-
powerOff: systemMethod(deviceInput$2, PowerSourceActionResultSchema, {
|
|
50906
|
-
kind: "mutation",
|
|
50907
|
-
auth: "admin"
|
|
50908
|
-
}),
|
|
50909
|
-
forceRestart: systemMethod(deviceInput$2, PowerSourceActionResultSchema, {
|
|
50910
|
-
kind: "mutation",
|
|
50911
|
-
auth: "admin"
|
|
50912
|
-
})
|
|
50913
|
-
},
|
|
50914
|
-
runtimeState: PowerSourceStateSchema,
|
|
50915
|
-
customize: powerSourceCustomize,
|
|
50916
|
-
/**
|
|
50917
|
-
* Runtime-state durability: **session** — mirrored from the linked switch on
|
|
50918
|
-
* its next report; a restored value would outlive the reading it names.
|
|
50919
|
-
*
|
|
50920
|
-
* See `RuntimeStateDurability`. Enforced by
|
|
50921
|
-
* `scripts/check-runtime-state-durability.ts`.
|
|
50922
|
-
*/
|
|
50923
|
-
durability: "session",
|
|
50924
|
-
history: "none"
|
|
50925
|
-
};
|
|
50926
51072
|
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
50927
51073
|
DeviceType.Camera;
|
|
50928
51074
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
@@ -50950,6 +51096,168 @@ var ComposableCapabilitiesSchema = object({ caps: array(object({
|
|
|
50950
51096
|
}).optional()
|
|
50951
51097
|
})) });
|
|
50952
51098
|
/**
|
|
51099
|
+
* A saved Customize assignment (D936). The schema is the type: callers use
|
|
51100
|
+
* `z.infer`, they do not restate the shape.
|
|
51101
|
+
*/
|
|
51102
|
+
var OverrideSourceSchema = object({
|
|
51103
|
+
addonId: string().min(1),
|
|
51104
|
+
stableId: string().min(1),
|
|
51105
|
+
cap: string().min(1),
|
|
51106
|
+
fieldPath: string().min(1)
|
|
51107
|
+
});
|
|
51108
|
+
var IdentityTransformDraftSchema = object({ kind: literal("identity") });
|
|
51109
|
+
var InvertTransformDraftSchema = object({ kind: literal("invert") });
|
|
51110
|
+
var ThresholdTransformDraftSchema = object({
|
|
51111
|
+
kind: literal("threshold"),
|
|
51112
|
+
comparison: _enum(["gte", "lte"]),
|
|
51113
|
+
threshold: number(),
|
|
51114
|
+
startDwellMs: number().nonnegative(),
|
|
51115
|
+
stopDwellMs: number().nonnegative()
|
|
51116
|
+
});
|
|
51117
|
+
var CustomizeTransformDraftSchema = discriminatedUnion("kind", [
|
|
51118
|
+
IdentityTransformDraftSchema,
|
|
51119
|
+
InvertTransformDraftSchema,
|
|
51120
|
+
ThresholdTransformDraftSchema,
|
|
51121
|
+
object({
|
|
51122
|
+
kind: literal("linear"),
|
|
51123
|
+
scale: number(),
|
|
51124
|
+
offset: number(),
|
|
51125
|
+
clampMin: number().optional(),
|
|
51126
|
+
clampMax: number().optional()
|
|
51127
|
+
}),
|
|
51128
|
+
object({
|
|
51129
|
+
kind: literal("enum-map"),
|
|
51130
|
+
mapping: record(string(), string().nullable())
|
|
51131
|
+
}),
|
|
51132
|
+
object({ kind: literal("number") })
|
|
51133
|
+
]);
|
|
51134
|
+
var ScalarOverrideDraftSchema = object({
|
|
51135
|
+
kind: literal("scalar"),
|
|
51136
|
+
cap: string().min(1),
|
|
51137
|
+
targetId: string().min(1),
|
|
51138
|
+
source: OverrideSourceSchema,
|
|
51139
|
+
transform: CustomizeTransformDraftSchema
|
|
51140
|
+
});
|
|
51141
|
+
var KeyedArrayOverrideDraftSchema = object({
|
|
51142
|
+
kind: literal("keyedArray"),
|
|
51143
|
+
cap: string().min(1),
|
|
51144
|
+
targetId: string().min(1),
|
|
51145
|
+
key: string().min(1),
|
|
51146
|
+
label: string().min(1),
|
|
51147
|
+
fieldPath: string().min(1),
|
|
51148
|
+
source: OverrideSourceSchema,
|
|
51149
|
+
transform: CustomizeTransformDraftSchema
|
|
51150
|
+
});
|
|
51151
|
+
var PulseOverrideDraftSchema = object({
|
|
51152
|
+
kind: literal("pulse"),
|
|
51153
|
+
cap: string().min(1),
|
|
51154
|
+
targetId: string().min(1),
|
|
51155
|
+
enabled: boolean(),
|
|
51156
|
+
debounceMs: number().nonnegative(),
|
|
51157
|
+
edges: array(_enum([
|
|
51158
|
+
"rising",
|
|
51159
|
+
"button",
|
|
51160
|
+
"native-event"
|
|
51161
|
+
])).min(1).optional(),
|
|
51162
|
+
sources: array(OverrideSourceSchema).min(1)
|
|
51163
|
+
});
|
|
51164
|
+
var SpanSourceDraftSchema = OverrideSourceSchema.extend({ mode: _enum([
|
|
51165
|
+
"in-addition",
|
|
51166
|
+
"confirm",
|
|
51167
|
+
"replace"
|
|
51168
|
+
]).optional() });
|
|
51169
|
+
discriminatedUnion("kind", [
|
|
51170
|
+
ScalarOverrideDraftSchema,
|
|
51171
|
+
KeyedArrayOverrideDraftSchema,
|
|
51172
|
+
PulseOverrideDraftSchema,
|
|
51173
|
+
object({
|
|
51174
|
+
kind: literal("span"),
|
|
51175
|
+
cap: string().min(1),
|
|
51176
|
+
targetId: string().min(1),
|
|
51177
|
+
timeoutMs: number().nonnegative(),
|
|
51178
|
+
cooldownMs: number().nonnegative().optional(),
|
|
51179
|
+
sources: array(SpanSourceDraftSchema)
|
|
51180
|
+
})
|
|
51181
|
+
]);
|
|
51182
|
+
object({
|
|
51183
|
+
targetId: string().min(1),
|
|
51184
|
+
configured: boolean(),
|
|
51185
|
+
source: _enum(["native", "assigned"]),
|
|
51186
|
+
state: _enum([
|
|
51187
|
+
"active",
|
|
51188
|
+
"stale",
|
|
51189
|
+
"released",
|
|
51190
|
+
"unavailable"
|
|
51191
|
+
]),
|
|
51192
|
+
reason: string().nullable()
|
|
51193
|
+
});
|
|
51194
|
+
/**
|
|
51195
|
+
* What a running-threshold proposal says (planning#405). The schema is the
|
|
51196
|
+
* type: the algorithm, the capability method and the UI all read `z.infer`.
|
|
51197
|
+
*
|
|
51198
|
+
* A proposal is read-only advice: it carries the numbers it was derived from
|
|
51199
|
+
* (`evidence`) so the operator can judge it, and an `insufficient` answer names
|
|
51200
|
+
* WHY with a typed reason and the catalog defaults, never an invented number.
|
|
51201
|
+
*/
|
|
51202
|
+
var RunningProposalTierSchema = _enum(["raw", "5m"]);
|
|
51203
|
+
var RunningProposalConfidenceSchema = _enum([
|
|
51204
|
+
"high",
|
|
51205
|
+
"medium",
|
|
51206
|
+
"low"
|
|
51207
|
+
]);
|
|
51208
|
+
var RunningProposalInsufficientReasonSchema = _enum([
|
|
51209
|
+
"no-history",
|
|
51210
|
+
"span-too-short",
|
|
51211
|
+
"truncated",
|
|
51212
|
+
"no-idle-floor",
|
|
51213
|
+
"no-runs",
|
|
51214
|
+
"no-separation"
|
|
51215
|
+
]);
|
|
51216
|
+
var RunningProposalReplaySchema = object({
|
|
51217
|
+
/** Intervals the real dwell expression held true over the window. */
|
|
51218
|
+
intervals: number().int().nonnegative(),
|
|
51219
|
+
/** Intervals outside every run, or a second interval inside one. */
|
|
51220
|
+
extra: number().int().nonnegative(),
|
|
51221
|
+
/** Runs without an interval of their own (none, or merged into a neighbour). */
|
|
51222
|
+
missed: number().int().nonnegative()
|
|
51223
|
+
});
|
|
51224
|
+
var RunningProposalEvidenceSchema = object({
|
|
51225
|
+
tier: RunningProposalTierSchema,
|
|
51226
|
+
spanMs: number().nonnegative(),
|
|
51227
|
+
from: number(),
|
|
51228
|
+
to: number(),
|
|
51229
|
+
points: number().int().nonnegative(),
|
|
51230
|
+
runsFound: number().int().nonnegative(),
|
|
51231
|
+
pausesFound: number().int().nonnegative(),
|
|
51232
|
+
longestPauseMs: number().nonnegative(),
|
|
51233
|
+
/** Episodes shorter than ~90 s (an anti-crease pulse, a display waking): never a run, never a pause. */
|
|
51234
|
+
pulsesFound: number().int().nonnegative(),
|
|
51235
|
+
longestPulseMs: number().nonnegative(),
|
|
51236
|
+
idleFloorW: number(),
|
|
51237
|
+
noiseCeilingW: number(),
|
|
51238
|
+
plateauW: number(),
|
|
51239
|
+
replay: RunningProposalReplaySchema
|
|
51240
|
+
});
|
|
51241
|
+
var RunningProposalInsufficientEvidenceSchema = object({
|
|
51242
|
+
spanMs: number().nonnegative(),
|
|
51243
|
+
points: number().int().nonnegative(),
|
|
51244
|
+
runsFound: number().int().nonnegative()
|
|
51245
|
+
});
|
|
51246
|
+
var RunningThresholdProposalSchema = discriminatedUnion("state", [object({
|
|
51247
|
+
state: literal("proposal"),
|
|
51248
|
+
transform: ThresholdTransformDraftSchema,
|
|
51249
|
+
evidence: RunningProposalEvidenceSchema,
|
|
51250
|
+
confidence: RunningProposalConfidenceSchema,
|
|
51251
|
+
/** Why the confidence is not higher; empty when nothing held it back. */
|
|
51252
|
+
notes: array(string())
|
|
51253
|
+
}), object({
|
|
51254
|
+
state: literal("insufficient"),
|
|
51255
|
+
reason: RunningProposalInsufficientReasonSchema,
|
|
51256
|
+
evidence: RunningProposalInsufficientEvidenceSchema,
|
|
51257
|
+
/** The catalog defaults, offered as what stands when nothing better is known. */
|
|
51258
|
+
fallback: ThresholdTransformDraftSchema
|
|
51259
|
+
})]);
|
|
51260
|
+
/**
|
|
50953
51261
|
* The report of a one-shot "move this owner's plaintext secrets into the
|
|
50954
51262
|
* keychain" run (D878). COUNTS only - never a value, never a ref.
|
|
50955
51263
|
*
|
|
@@ -51246,6 +51554,14 @@ method(object({}), object({ blocks: array(CoreBlockSchema) }), { auth: "admin" }
|
|
|
51246
51554
|
kind: "mutation",
|
|
51247
51555
|
auth: "admin",
|
|
51248
51556
|
access: "view"
|
|
51557
|
+
}), method(object({
|
|
51558
|
+
deviceId: number().int(),
|
|
51559
|
+
cap: string().min(1),
|
|
51560
|
+
fieldPath: string().min(1),
|
|
51561
|
+
deviceType: _enum(DeviceType).optional()
|
|
51562
|
+
}), RunningThresholdProposalSchema, {
|
|
51563
|
+
auth: "admin",
|
|
51564
|
+
access: "view"
|
|
51249
51565
|
}), method(object({
|
|
51250
51566
|
blockId: string().min(1),
|
|
51251
51567
|
trace: AutomationRunTraceSchema.optional(),
|
|
@@ -52207,7 +52523,27 @@ method(object({
|
|
|
52207
52523
|
* exposes only the COMMON surface: link state, supported device
|
|
52208
52524
|
* kinds (so the UI can filter the device picker), and per-device
|
|
52209
52525
|
* expose/unexpose.
|
|
52210
|
-
|
|
52526
|
+
*
|
|
52527
|
+
* INSTANCES. One export addon can serve several independent targets (a
|
|
52528
|
+
* HomeKit bridge, a Home Assistant broker). `listInstances` names them.
|
|
52529
|
+
* `instanceId` on a READ is optional: absent = the whole addon (linked if any
|
|
52530
|
+
* enabled instance is, `exposedDeviceCount` = distinct devices, `setup` = the
|
|
52531
|
+
* default instance's); present = that instance; an id the provider does not
|
|
52532
|
+
* serve is refused with `ExportInstanceUnknownError` (`export-instance-unknown`),
|
|
52533
|
+
* never answered empty. `instanceId` on a WRITE is REQUIRED: a membership
|
|
52534
|
+
* change always names the target it changes. A single-instance provider
|
|
52535
|
+
* accepts an absent id on a read or its own id, and refuses any other.
|
|
52536
|
+
*/
|
|
52537
|
+
/** Which instance of an export addon a call addresses. Absent on a read = the whole addon. */
|
|
52538
|
+
var InstanceIdSchema$1 = string().min(1);
|
|
52539
|
+
var InstancePinSchema = object({ instanceId: InstanceIdSchema$1.optional() });
|
|
52540
|
+
/** One independent export target of an addon. */
|
|
52541
|
+
var ExportInstanceSchema = object({
|
|
52542
|
+
instanceId: InstanceIdSchema$1,
|
|
52543
|
+
name: string(),
|
|
52544
|
+
enabled: boolean(),
|
|
52545
|
+
kind: string().optional()
|
|
52546
|
+
});
|
|
52211
52547
|
var LinkStateSchema = _enum([
|
|
52212
52548
|
"unlinked",
|
|
52213
52549
|
"linked",
|
|
@@ -52258,10 +52594,14 @@ var ExposedDeviceSchema = object({
|
|
|
52258
52594
|
capabilities: array(string()).optional()
|
|
52259
52595
|
});
|
|
52260
52596
|
var ExposeInputSchema = object({
|
|
52597
|
+
instanceId: InstanceIdSchema$1,
|
|
52261
52598
|
deviceId: string(),
|
|
52262
52599
|
capabilities: array(string()).optional()
|
|
52263
52600
|
});
|
|
52264
|
-
var UnexposeInputSchema = object({
|
|
52601
|
+
var UnexposeInputSchema = object({
|
|
52602
|
+
instanceId: InstanceIdSchema$1,
|
|
52603
|
+
deviceId: string()
|
|
52604
|
+
});
|
|
52265
52605
|
/**
|
|
52266
52606
|
* What an exporter may expose besides devices (D968). An action and a
|
|
52267
52607
|
* notification target are LIST ENTRIES, never devices (D954): they enter an
|
|
@@ -52290,15 +52630,21 @@ var ExposedEntitySchema = object({
|
|
|
52290
52630
|
entity: ExportEntityRefSchema,
|
|
52291
52631
|
exposedAs: string().optional()
|
|
52292
52632
|
});
|
|
52293
|
-
var ExposeEntityInputSchema = object({
|
|
52294
|
-
|
|
52295
|
-
|
|
52633
|
+
var ExposeEntityInputSchema = object({
|
|
52634
|
+
instanceId: InstanceIdSchema$1,
|
|
52635
|
+
entity: ExportEntityRefSchema
|
|
52636
|
+
});
|
|
52637
|
+
var UnexposeEntityInputSchema = object({
|
|
52638
|
+
instanceId: InstanceIdSchema$1,
|
|
52639
|
+
entity: ExportEntityRefSchema
|
|
52640
|
+
});
|
|
52641
|
+
method(InstancePinSchema, DeviceExportStatusSchema), method(_void(), array(ExportInstanceSchema)), method(InstancePinSchema, array(DeviceKindSchema)), method(InstancePinSchema, array(ExposedDeviceSchema)), method(ExposeInputSchema, _void(), {
|
|
52296
52642
|
kind: "mutation",
|
|
52297
52643
|
auth: "admin"
|
|
52298
52644
|
}), method(UnexposeInputSchema, _void(), {
|
|
52299
52645
|
kind: "mutation",
|
|
52300
52646
|
auth: "admin"
|
|
52301
|
-
}), optionalMethod(_void(), array(ExportEntityKindSchema)), optionalMethod(
|
|
52647
|
+
}), optionalMethod(_void(), array(ExportEntityKindSchema)), optionalMethod(InstancePinSchema, array(ExposedEntitySchema)), optionalMethod(ExposeEntityInputSchema, _void(), {
|
|
52302
52648
|
kind: "mutation",
|
|
52303
52649
|
auth: "admin"
|
|
52304
52650
|
}), optionalMethod(UnexposeEntityInputSchema, _void(), {
|
|
@@ -55943,15 +56289,15 @@ var FanPresetCaptureResultSchema = object({
|
|
|
55943
56289
|
items: array(FanCaptureItemSchema),
|
|
55944
56290
|
omitted: array(FanCaptureOmissionSchema)
|
|
55945
56291
|
});
|
|
55946
|
-
var deviceInput$
|
|
56292
|
+
var deviceInput$2 = object({ deviceId: number().int().nonnegative() });
|
|
55947
56293
|
DeviceType.Fan;
|
|
55948
|
-
method(deviceInput$
|
|
56294
|
+
method(deviceInput$2, array(FanPresetSchema), { auth: "protected" }), method(deviceInput$2.extend({ presets: array(FanPresetSchema).max(12) }), FanPresetsSetResultSchema, {
|
|
55949
56295
|
kind: "mutation",
|
|
55950
56296
|
auth: "admin"
|
|
55951
|
-
}), method(deviceInput$
|
|
56297
|
+
}), method(deviceInput$2.extend({ presetId: string().min(1) }), FanPresetApplyResultSchema, {
|
|
55952
56298
|
kind: "mutation",
|
|
55953
56299
|
auth: "protected"
|
|
55954
|
-
}), method(deviceInput$
|
|
56300
|
+
}), method(deviceInput$2.extend({
|
|
55955
56301
|
fields: array(FanCaptureFieldSchema).optional(),
|
|
55956
56302
|
steps: array(ActionStepSchema).max(20).default([])
|
|
55957
56303
|
}), FanPresetCaptureResultSchema, { auth: "protected" });
|
|
@@ -56834,6 +57180,12 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
|
|
|
56834
57180
|
}), object({ success: boolean() }), {
|
|
56835
57181
|
kind: "mutation",
|
|
56836
57182
|
auth: "admin"
|
|
57183
|
+
}), method(object({ id: string() }), object({
|
|
57184
|
+
rows: number().int().nonnegative(),
|
|
57185
|
+
secrets: number().int().nonnegative()
|
|
57186
|
+
}), {
|
|
57187
|
+
kind: "mutation",
|
|
57188
|
+
auth: "admin"
|
|
56837
57189
|
}), method(_void(), array(AvailableIntegrationTypeSchema), { auth: "admin" }), method(object({
|
|
56838
57190
|
addonId: string(),
|
|
56839
57191
|
settings: record(string(), unknown())
|
|
@@ -56862,13 +57214,65 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
|
|
|
56862
57214
|
*/
|
|
56863
57215
|
var ConfigSchemaPassthrough$3 = custom();
|
|
56864
57216
|
var IntegrationInstanceIdSchema = string().min(1);
|
|
57217
|
+
var IntegrationInstanceModeSchema = _enum(["single", "multiple"]);
|
|
57218
|
+
/**
|
|
57219
|
+
* One kind of instance a provider can create (an adapter, an account type). The sign-in and
|
|
57220
|
+
* connect fields follow the `broker` contract (`broker.cap.ts`): `signIn.basePath` is a
|
|
57221
|
+
* hub-relative route set speaking the sign-in contract, `connectPath` / `disconnectPath` open an
|
|
57222
|
+
* interactive account link (popup) and may carry `{{brokerId}}`, which the UI replaces with the
|
|
57223
|
+
* instance id.
|
|
57224
|
+
*/
|
|
57225
|
+
var IntegrationInstanceKindSchema = object({
|
|
57226
|
+
/** Stable id of the kind, sent back as `createInstance.kind`. */
|
|
57227
|
+
id: string().min(1),
|
|
57228
|
+
label: string().min(1),
|
|
57229
|
+
/** The kind signs in through a server-held interactive session. */
|
|
57230
|
+
signIn: object({
|
|
57231
|
+
basePath: string().min(1),
|
|
57232
|
+
methods: array(_enum(["device-code", "proxy"])).optional()
|
|
57233
|
+
}).optional(),
|
|
57234
|
+
/** Relative hub path to start an interactive account link of an instance of this kind. */
|
|
57235
|
+
connectPath: string().min(1).optional(),
|
|
57236
|
+
/** Relative hub path to disconnect that account. */
|
|
57237
|
+
disconnectPath: string().min(1).optional()
|
|
57238
|
+
});
|
|
56865
57239
|
var IntegrationInstanceDescriptionSchema = object({
|
|
57240
|
+
/** What the instances are for the Integrations page; see {@link IntegrationInstanceRoleSchema}. */
|
|
57241
|
+
role: _enum([
|
|
57242
|
+
"devices",
|
|
57243
|
+
"services",
|
|
57244
|
+
"both"
|
|
57245
|
+
]),
|
|
57246
|
+
/** How the devices of an instance are found; absent means `{ mode: 'none' }`. */
|
|
57247
|
+
discovery: object({
|
|
57248
|
+
mode: _enum([
|
|
57249
|
+
"none",
|
|
57250
|
+
"lan",
|
|
57251
|
+
"account"
|
|
57252
|
+
]),
|
|
57253
|
+
scopedToInstance: boolean()
|
|
57254
|
+
}).optional(),
|
|
56866
57255
|
/** `single`: at most one instance can exist (Loki). `multiple`: an account each. */
|
|
56867
|
-
instanceMode:
|
|
57256
|
+
instanceMode: IntegrationInstanceModeSchema,
|
|
56868
57257
|
/** What the instance is, for the UI (`destination`, `relay`, `account`). */
|
|
56869
57258
|
kind: string(),
|
|
56870
57259
|
/** True when `testInstance` really probes the remote. */
|
|
56871
|
-
canTest: boolean()
|
|
57260
|
+
canTest: boolean(),
|
|
57261
|
+
/**
|
|
57262
|
+
* The kinds an instance can be of. Absent or one entry: nothing to choose; more than one: the
|
|
57263
|
+
* Add flow asks which first and sends it as `createInstance.kind`.
|
|
57264
|
+
*/
|
|
57265
|
+
kinds: array(IntegrationInstanceKindSchema).optional(),
|
|
57266
|
+
/**
|
|
57267
|
+
* The provider accepts `createInstance.id` for an id that once existed (an adopted id, because
|
|
57268
|
+
* devices carry it). The UI then offers "restore under its old id" on Add. Absent means no.
|
|
57269
|
+
*/
|
|
57270
|
+
allowRestoreId: boolean().optional(),
|
|
57271
|
+
/**
|
|
57272
|
+
* `createInstance` without an `id` works: the provider mints it. Absent means the caller must
|
|
57273
|
+
* send an id (the UI then mints an opaque one).
|
|
57274
|
+
*/
|
|
57275
|
+
mintsId: boolean().optional()
|
|
56872
57276
|
});
|
|
56873
57277
|
var IntegrationInstanceStatusSchema = object({
|
|
56874
57278
|
state: _enum([
|
|
@@ -56877,7 +57281,9 @@ var IntegrationInstanceStatusSchema = object({
|
|
|
56877
57281
|
"error",
|
|
56878
57282
|
"unknown"
|
|
56879
57283
|
]),
|
|
56880
|
-
detail: string().optional()
|
|
57284
|
+
detail: string().optional(),
|
|
57285
|
+
/** A short human word for the state ("Signed in", "Token expired"); shown instead of `state`. */
|
|
57286
|
+
label: string().optional()
|
|
56881
57287
|
});
|
|
56882
57288
|
var IntegrationInstanceSchema = object({
|
|
56883
57289
|
id: IntegrationInstanceIdSchema,
|
|
@@ -56885,13 +57291,18 @@ var IntegrationInstanceSchema = object({
|
|
|
56885
57291
|
/** The addon's own rule (an URL is present, a client id is present...). */
|
|
56886
57292
|
configured: boolean(),
|
|
56887
57293
|
/**
|
|
56888
|
-
* The instance's own on/off switch (D996)
|
|
56889
|
-
*
|
|
57294
|
+
* The instance's own on/off switch (D996), derived from the record body (`enabled !== false`,
|
|
57295
|
+
* so a row written before the field existed is on). Absent when the `integrations` registry
|
|
57296
|
+
* owns the switch (`describe().role` is `devices`): read it from the registry row.
|
|
56890
57297
|
*/
|
|
56891
|
-
enabled: boolean(),
|
|
57298
|
+
enabled: boolean().optional(),
|
|
57299
|
+
/** The kind of this instance (one of `describe().kinds[].id`), when the provider has kinds. */
|
|
57300
|
+
kind: string().optional(),
|
|
56892
57301
|
/** Values for the instance form; a secret is a `SecretFieldView`, never text. */
|
|
56893
57302
|
formValues: record(string(), unknown()),
|
|
56894
|
-
status: IntegrationInstanceStatusSchema.optional()
|
|
57303
|
+
status: IntegrationInstanceStatusSchema.optional(),
|
|
57304
|
+
/** Epoch ms of the last probe of the remote that produced `status`; absent when never checked. */
|
|
57305
|
+
lastCheckedAt: number().optional()
|
|
56895
57306
|
});
|
|
56896
57307
|
var IntegrationInstancePatchSchema = object({
|
|
56897
57308
|
id: IntegrationInstanceIdSchema,
|
|
@@ -56900,8 +57311,9 @@ var IntegrationInstancePatchSchema = object({
|
|
|
56900
57311
|
values: record(string(), unknown())
|
|
56901
57312
|
});
|
|
56902
57313
|
method(_void(), IntegrationInstanceDescriptionSchema, { auth: "admin" }), method(object({ id: IntegrationInstanceIdSchema.nullable() }), ConfigSchemaPassthrough$3, { auth: "admin" }), method(_void(), array(IntegrationInstanceSchema).readonly(), { auth: "admin" }), method(object({ id: IntegrationInstanceIdSchema }), IntegrationInstanceSchema.nullable(), { auth: "admin" }), method(object({
|
|
56903
|
-
id: IntegrationInstanceIdSchema,
|
|
56904
|
-
name: string().min(1)
|
|
57314
|
+
id: IntegrationInstanceIdSchema.optional(),
|
|
57315
|
+
name: string().min(1),
|
|
57316
|
+
kind: string().min(1).optional()
|
|
56905
57317
|
}), object({ id: string() }), {
|
|
56906
57318
|
kind: "mutation",
|
|
56907
57319
|
auth: "admin"
|
|
@@ -59061,6 +59473,11 @@ var LogEntrySchema = object({
|
|
|
59061
59473
|
* flight, and not asking for the next slice ends the scan.
|
|
59062
59474
|
*/
|
|
59063
59475
|
var LogReadQuerySchema = object({
|
|
59476
|
+
/**
|
|
59477
|
+
* Which destination INSTANCE answers (a destination addon may hold several records). Absent ⇒
|
|
59478
|
+
* the provider's first readable one, so a caller written before instances existed is unchanged.
|
|
59479
|
+
*/
|
|
59480
|
+
instanceId: string().min(1).max(200).optional(),
|
|
59064
59481
|
/** Correlates `cancelRead`. Caller-chosen, unique per in-flight read. */
|
|
59065
59482
|
requestId: string().min(1).max(64).optional(),
|
|
59066
59483
|
/** The device the line is about (`tags.deviceId`, numeric). */
|
|
@@ -59123,6 +59540,8 @@ var LogReadResultSchema = object({
|
|
|
59123
59540
|
/** True when `cancelRead` ended this slice early. */
|
|
59124
59541
|
cancelled: boolean().optional()
|
|
59125
59542
|
});
|
|
59543
|
+
/** Names one destination instance; absent ⇒ the provider's first readable one. */
|
|
59544
|
+
var LogInstanceSelectorSchema = object({ instanceId: string().min(1).max(200).optional() });
|
|
59126
59545
|
var LogReadCapabilitiesSchema = object({
|
|
59127
59546
|
/** False ⇒ this destination only ships lines (console, forwarder, an unconfigured Loki). */
|
|
59128
59547
|
readable: boolean(),
|
|
@@ -59141,7 +59560,7 @@ var LogReadCapabilitiesSchema = object({
|
|
|
59141
59560
|
/** How far back the store reaches, when the provider knows (days). */
|
|
59142
59561
|
retentionDays: number().nullable()
|
|
59143
59562
|
});
|
|
59144
|
-
method(LogEntrySchema, _void(), { kind: "mutation" }), optionalMethod(
|
|
59563
|
+
method(LogEntrySchema, _void(), { kind: "mutation" }), optionalMethod(LogInstanceSelectorSchema, LogReadCapabilitiesSchema, { auth: "admin" }), optionalMethod(LogReadQuerySchema, LogReadResultSchema, { auth: "admin" }), optionalMethod(object({ requestId: string().min(1).max(64) }), object({ cancelled: boolean() }), {
|
|
59145
59564
|
kind: "mutation",
|
|
59146
59565
|
auth: "admin"
|
|
59147
59566
|
});
|
|
@@ -59245,214 +59664,6 @@ var LoginMethodContributionSchema = discriminatedUnion("kind", [
|
|
|
59245
59664
|
]);
|
|
59246
59665
|
method(_void(), array(LoginMethodContributionSchema).readonly());
|
|
59247
59666
|
/**
|
|
59248
|
-
* Media-player cap. Models HA `media_player.*` (Sonos, Chromecast,
|
|
59249
|
-
* Apple TV, Spotify, Roku, generic OTT receivers, …) on
|
|
59250
|
-
* `DeviceType.MediaPlayer`. Disjoint from the camera streaming
|
|
59251
|
-
* surface — those use `DeviceType.Camera` + the broker pipeline.
|
|
59252
|
-
*
|
|
59253
|
-
* The cap declares a wide method surface; not every backend supports
|
|
59254
|
-
* every method. Drivers signal sub-capability via the
|
|
59255
|
-
* `DeviceFeature.MediaPlayerXxx` flags (paired one-to-one with the
|
|
59256
|
-
* corresponding method) so the UI gates buttons without a slice
|
|
59257
|
-
* fetch — same pattern as `PanTiltZoom` for cameras.
|
|
59258
|
-
*/
|
|
59259
|
-
var MediaPlayerStateSchema = _enum([
|
|
59260
|
-
"off",
|
|
59261
|
-
"on",
|
|
59262
|
-
"idle",
|
|
59263
|
-
"playing",
|
|
59264
|
-
"paused",
|
|
59265
|
-
"buffering",
|
|
59266
|
-
"standby"
|
|
59267
|
-
]);
|
|
59268
|
-
var MediaPlayerRepeatSchema = _enum([
|
|
59269
|
-
"off",
|
|
59270
|
-
"all",
|
|
59271
|
-
"one"
|
|
59272
|
-
]);
|
|
59273
|
-
var MediaInfoSchema = object({
|
|
59274
|
-
/** Free-form media kind (`music`, `tvshow`, `movie`, `app`, `channel`,
|
|
59275
|
-
* `podcast`, …). */
|
|
59276
|
-
type: string(),
|
|
59277
|
-
/** Human-readable title. */
|
|
59278
|
-
title: string(),
|
|
59279
|
-
/** Optional artist / channel / station label. */
|
|
59280
|
-
artist: string().optional(),
|
|
59281
|
-
/** Optional album / season / show name. */
|
|
59282
|
-
album: string().optional(),
|
|
59283
|
-
/** Optional cover-art / thumbnail URL. */
|
|
59284
|
-
imageUrl: string().optional()
|
|
59285
|
-
});
|
|
59286
|
-
/**
|
|
59287
|
-
* Where `state`, `volumeLevel`, `isMuted` and `source` come from. `reported`:
|
|
59288
|
-
* the device said so. `assumed`: the driver has no feedback (infrared) and
|
|
59289
|
-
* tracks what it last SENT; it moves only after a send was accepted, and a
|
|
59290
|
-
* human at the real remote makes it wrong. A UI shows an assumed value as a
|
|
59291
|
-
* guess, never as a reading.
|
|
59292
|
-
*/
|
|
59293
|
-
var MediaPlayerStateSourceSchema = _enum(["reported", "assumed"]);
|
|
59294
|
-
/** The fields of a media-player status a driver can only guess. */
|
|
59295
|
-
var MediaPlayerAssumedFieldSchema = _enum([
|
|
59296
|
-
"state",
|
|
59297
|
-
"volumeLevel",
|
|
59298
|
-
"isMuted",
|
|
59299
|
-
"source"
|
|
59300
|
-
]);
|
|
59301
|
-
var MediaPlayerStatusSchema = object({
|
|
59302
|
-
/** Playback lifecycle state. */
|
|
59303
|
-
state: MediaPlayerStateSchema,
|
|
59304
|
-
/**
|
|
59305
|
-
* Whether the state fields are readings or the driver's own bookkeeping.
|
|
59306
|
-
* A slice written before this field existed parses as `reported`.
|
|
59307
|
-
*/
|
|
59308
|
-
stateSource: MediaPlayerStateSourceSchema.default("reported"),
|
|
59309
|
-
/**
|
|
59310
|
-
* Which fields are the driver's own guess. `stateSource` is `assumed` when
|
|
59311
|
-
* this is not empty; a field not listed here is a reading even then (power
|
|
59312
|
-
* from a running-state source, mute guessed from the last send).
|
|
59313
|
-
*/
|
|
59314
|
-
assumedFields: array(MediaPlayerAssumedFieldSchema).default([]),
|
|
59315
|
-
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
59316
|
-
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
59317
|
-
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59318
|
-
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
59319
|
-
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
59320
|
-
isMuted: boolean().nullable(),
|
|
59321
|
-
/** Active source / input. Empty when no source surface. */
|
|
59322
|
-
source: string(),
|
|
59323
|
-
/** Selectable sources. Empty when no source surface.
|
|
59324
|
-
* Pair with `DeviceFeature.MediaPlayerSelectSource`. */
|
|
59325
|
-
availableSources: array(string()),
|
|
59326
|
-
/** Currently-playing media info. Null when nothing is playing. */
|
|
59327
|
-
currentMedia: MediaInfoSchema.nullable(),
|
|
59328
|
-
/** Current playback position in ms. Null when not seekable or
|
|
59329
|
-
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
59330
|
-
position: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
59331
|
-
/** Total duration of the current media in ms. Null when unknown
|
|
59332
|
-
* (live stream) or nothing is playing. */
|
|
59333
|
-
duration: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
59334
|
-
/** Shuffle toggle. Null when no shuffle surface.
|
|
59335
|
-
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
59336
|
-
shuffle: boolean().nullable(),
|
|
59337
|
-
/** Repeat mode. Null when no repeat surface.
|
|
59338
|
-
* Pair with `DeviceFeature.MediaPlayerRepeat`. */
|
|
59339
|
-
repeat: MediaPlayerRepeatSchema.nullable(),
|
|
59340
|
-
/** Ms epoch when the slice was last updated. */
|
|
59341
|
-
lastChangedAt: number()
|
|
59342
|
-
});
|
|
59343
|
-
var mediaPlayerCapability = {
|
|
59344
|
-
name: "media-player",
|
|
59345
|
-
scope: "device",
|
|
59346
|
-
deviceNative: true,
|
|
59347
|
-
mode: "singleton",
|
|
59348
|
-
deviceTypes: [DeviceType.MediaPlayer],
|
|
59349
|
-
methods: {
|
|
59350
|
-
play: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
59351
|
-
kind: "mutation",
|
|
59352
|
-
auth: "protected"
|
|
59353
|
-
}),
|
|
59354
|
-
pause: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
59355
|
-
kind: "mutation",
|
|
59356
|
-
auth: "protected"
|
|
59357
|
-
}),
|
|
59358
|
-
stop: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
59359
|
-
kind: "mutation",
|
|
59360
|
-
auth: "protected"
|
|
59361
|
-
}),
|
|
59362
|
-
next: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
59363
|
-
kind: "mutation",
|
|
59364
|
-
auth: "protected"
|
|
59365
|
-
}),
|
|
59366
|
-
previous: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
59367
|
-
kind: "mutation",
|
|
59368
|
-
auth: "protected"
|
|
59369
|
-
}),
|
|
59370
|
-
seek: method(object({
|
|
59371
|
-
deviceId: number().int().nonnegative(),
|
|
59372
|
-
position: number().int().nonnegative()
|
|
59373
|
-
}), _void(), {
|
|
59374
|
-
kind: "mutation",
|
|
59375
|
-
auth: "protected"
|
|
59376
|
-
}),
|
|
59377
|
-
setVolume: method(object({
|
|
59378
|
-
deviceId: number().int().nonnegative(),
|
|
59379
|
-
volumeLevel: number().min(0).max(100)
|
|
59380
|
-
}), _void(), {
|
|
59381
|
-
kind: "mutation",
|
|
59382
|
-
auth: "protected"
|
|
59383
|
-
}),
|
|
59384
|
-
setMute: method(object({
|
|
59385
|
-
deviceId: number().int().nonnegative(),
|
|
59386
|
-
muted: boolean()
|
|
59387
|
-
}), _void(), {
|
|
59388
|
-
kind: "mutation",
|
|
59389
|
-
auth: "protected"
|
|
59390
|
-
}),
|
|
59391
|
-
setShuffle: method(object({
|
|
59392
|
-
deviceId: number().int().nonnegative(),
|
|
59393
|
-
shuffle: boolean()
|
|
59394
|
-
}), _void(), {
|
|
59395
|
-
kind: "mutation",
|
|
59396
|
-
auth: "protected"
|
|
59397
|
-
}),
|
|
59398
|
-
setRepeat: method(object({
|
|
59399
|
-
deviceId: number().int().nonnegative(),
|
|
59400
|
-
repeat: MediaPlayerRepeatSchema
|
|
59401
|
-
}), _void(), {
|
|
59402
|
-
kind: "mutation",
|
|
59403
|
-
auth: "protected"
|
|
59404
|
-
}),
|
|
59405
|
-
selectSource: method(object({
|
|
59406
|
-
deviceId: number().int().nonnegative(),
|
|
59407
|
-
source: string().min(1)
|
|
59408
|
-
}), _void(), {
|
|
59409
|
-
kind: "mutation",
|
|
59410
|
-
auth: "protected"
|
|
59411
|
-
}),
|
|
59412
|
-
playMedia: method(object({
|
|
59413
|
-
deviceId: number().int().nonnegative(),
|
|
59414
|
-
/** Media identifier / URL. */
|
|
59415
|
-
mediaId: string().min(1),
|
|
59416
|
-
/** Media kind (`music`, `tvshow`, `movie`, `app`, …) — provider
|
|
59417
|
-
* passes it through to the upstream service. */
|
|
59418
|
-
mediaType: string().min(1)
|
|
59419
|
-
}), _void(), {
|
|
59420
|
-
kind: "mutation",
|
|
59421
|
-
auth: "protected"
|
|
59422
|
-
})
|
|
59423
|
-
},
|
|
59424
|
-
status: {
|
|
59425
|
-
schema: MediaPlayerStatusSchema,
|
|
59426
|
-
kind: "push"
|
|
59427
|
-
},
|
|
59428
|
-
/**
|
|
59429
|
-
* Runtime-state slice — mirrored by the kernel. UI players read the
|
|
59430
|
-
* full slice for live now-playing, volume, and progress updates
|
|
59431
|
-
* without polling.
|
|
59432
|
-
*/
|
|
59433
|
-
runtimeState: MediaPlayerStatusSchema,
|
|
59434
|
-
/**
|
|
59435
|
-
* Runtime-state durability: **session** — a restored transport position describes a playback that stopped when the hub did.
|
|
59436
|
-
*
|
|
59437
|
-
* See `RuntimeStateDurability`. Enforced by
|
|
59438
|
-
* `scripts/check-runtime-state-durability.ts`.
|
|
59439
|
-
*/
|
|
59440
|
-
durability: "session",
|
|
59441
|
-
/**
|
|
59442
|
-
* History (D850): volume (a level an operator or an automation sets; the
|
|
59443
|
-
* default 10 s floor folds a slider drag into its end value) and mute.
|
|
59444
|
-
* `position` is not recorded: it moves continuously while playing.
|
|
59445
|
-
*/
|
|
59446
|
-
history: { fields: {
|
|
59447
|
-
volumeLevel: {
|
|
59448
|
-
kind: "gauge",
|
|
59449
|
-
unit: "%",
|
|
59450
|
-
deadband: 1
|
|
59451
|
-
},
|
|
59452
|
-
isMuted: { kind: "boolean" }
|
|
59453
|
-
} }
|
|
59454
|
-
};
|
|
59455
|
-
/**
|
|
59456
59667
|
* mesh-network — collection cap for mesh-VPN providers.
|
|
59457
59668
|
*
|
|
59458
59669
|
* Different shape from `network-access` (public tunnels):
|
|
@@ -73536,6 +73747,14 @@ var powerMeterCapability = {
|
|
|
73536
73747
|
deviceNative: true,
|
|
73537
73748
|
mode: "singleton",
|
|
73538
73749
|
deviceTypes: POWER_METER_DEVICE_TYPES,
|
|
73750
|
+
deviceConfig: { ui: {
|
|
73751
|
+
kind: "widget",
|
|
73752
|
+
widgetId: "host/power-meter-line",
|
|
73753
|
+
tab: "power",
|
|
73754
|
+
placement: "hero",
|
|
73755
|
+
label: "Power",
|
|
73756
|
+
order: 4
|
|
73757
|
+
} },
|
|
73539
73758
|
methods: {},
|
|
73540
73759
|
status: {
|
|
73541
73760
|
schema: PowerMeterStatusSchema,
|
|
@@ -73595,6 +73814,117 @@ var powerMeterCapability = {
|
|
|
73595
73814
|
volatileStateFields: ["lastFetchedAt"],
|
|
73596
73815
|
customize: powerMeterCustomize
|
|
73597
73816
|
};
|
|
73817
|
+
var PowerSourceRefusalReasonSchema = _enum([
|
|
73818
|
+
"no-power-source",
|
|
73819
|
+
"switch-missing",
|
|
73820
|
+
"switch-offline",
|
|
73821
|
+
"switch-unknown",
|
|
73822
|
+
"restart-in-progress",
|
|
73823
|
+
"switch-call-failed"
|
|
73824
|
+
]);
|
|
73825
|
+
var PowerSourceActionResultSchema = discriminatedUnion("accepted", [object({ accepted: literal(true) }), object({
|
|
73826
|
+
accepted: literal(false),
|
|
73827
|
+
reason: PowerSourceRefusalReasonSchema,
|
|
73828
|
+
/** One line for the operator, naming the switch. */
|
|
73829
|
+
message: string()
|
|
73830
|
+
})]);
|
|
73831
|
+
var PowerSourceInfoSchema = object({
|
|
73832
|
+
/** False when the device has no power source linked; the rest is then empty. */
|
|
73833
|
+
linked: boolean(),
|
|
73834
|
+
switchDeviceId: number().nullable(),
|
|
73835
|
+
switchName: string().nullable(),
|
|
73836
|
+
/** The switch's on/off state, or null when it is unknown. Never false for unknown (D393). */
|
|
73837
|
+
switchOn: boolean().nullable(),
|
|
73838
|
+
switchOnline: boolean().nullable(),
|
|
73839
|
+
restartInProgress: boolean(),
|
|
73840
|
+
offSeconds: number().int()
|
|
73841
|
+
});
|
|
73842
|
+
/** The composed slice: the switch state the link mirrors, plus the stored off time. */
|
|
73843
|
+
var PowerSourceStateSchema = object({
|
|
73844
|
+
/** Null while the switch has not reported: unknown is never `false` (D393). */
|
|
73845
|
+
switchOn: boolean().nullable(),
|
|
73846
|
+
offSeconds: number().int(),
|
|
73847
|
+
lastFetchedAt: number()
|
|
73848
|
+
});
|
|
73849
|
+
var POWER_SOURCE_DEVICE_TYPES = [
|
|
73850
|
+
DeviceType.Gateway,
|
|
73851
|
+
DeviceType.Hub,
|
|
73852
|
+
DeviceType.Camera,
|
|
73853
|
+
DeviceType.Sensor,
|
|
73854
|
+
DeviceType.MediaPlayer,
|
|
73855
|
+
DeviceType.Vacuum,
|
|
73856
|
+
DeviceType.Generic,
|
|
73857
|
+
DeviceType.Washer,
|
|
73858
|
+
DeviceType.Dryer,
|
|
73859
|
+
DeviceType.Dishwasher,
|
|
73860
|
+
DeviceType.PetFountain,
|
|
73861
|
+
DeviceType.Fan,
|
|
73862
|
+
DeviceType.Humidifier,
|
|
73863
|
+
DeviceType.Climate,
|
|
73864
|
+
DeviceType.WaterHeater
|
|
73865
|
+
];
|
|
73866
|
+
var powerSourceCustomize = {
|
|
73867
|
+
version: 1,
|
|
73868
|
+
targets: [{
|
|
73869
|
+
id: "switch",
|
|
73870
|
+
cardinality: "scalar",
|
|
73871
|
+
vocabulary: {
|
|
73872
|
+
cap: "power-source",
|
|
73873
|
+
stateField: "switchOn"
|
|
73874
|
+
},
|
|
73875
|
+
deviceTypes: POWER_SOURCE_DEVICE_TYPES,
|
|
73876
|
+
apply: "add",
|
|
73877
|
+
path: "switchOn",
|
|
73878
|
+
sources: [{
|
|
73879
|
+
kind: "switch",
|
|
73880
|
+
transforms: [{ kind: "identity" }]
|
|
73881
|
+
}],
|
|
73882
|
+
companions: [{
|
|
73883
|
+
kind: "constant",
|
|
73884
|
+
path: "offSeconds",
|
|
73885
|
+
value: 10,
|
|
73886
|
+
when: "add"
|
|
73887
|
+
}, {
|
|
73888
|
+
kind: "clock",
|
|
73889
|
+
path: "lastFetchedAt",
|
|
73890
|
+
when: "always"
|
|
73891
|
+
}],
|
|
73892
|
+
sourceReport: { status: "assignment-status" }
|
|
73893
|
+
}]
|
|
73894
|
+
};
|
|
73895
|
+
var deviceInput$1 = object({ deviceId: number().int().nonnegative() });
|
|
73896
|
+
var powerSourceCapability = {
|
|
73897
|
+
name: "power-source",
|
|
73898
|
+
scope: "device",
|
|
73899
|
+
mode: "singleton",
|
|
73900
|
+
deviceTypes: POWER_SOURCE_DEVICE_TYPES,
|
|
73901
|
+
methods: {
|
|
73902
|
+
getStatus: systemMethod(deviceInput$1, PowerSourceInfoSchema, { auth: "admin" }),
|
|
73903
|
+
powerOn: systemMethod(deviceInput$1, PowerSourceActionResultSchema, {
|
|
73904
|
+
kind: "mutation",
|
|
73905
|
+
auth: "admin"
|
|
73906
|
+
}),
|
|
73907
|
+
powerOff: systemMethod(deviceInput$1, PowerSourceActionResultSchema, {
|
|
73908
|
+
kind: "mutation",
|
|
73909
|
+
auth: "admin"
|
|
73910
|
+
}),
|
|
73911
|
+
forceRestart: systemMethod(deviceInput$1, PowerSourceActionResultSchema, {
|
|
73912
|
+
kind: "mutation",
|
|
73913
|
+
auth: "admin"
|
|
73914
|
+
})
|
|
73915
|
+
},
|
|
73916
|
+
runtimeState: PowerSourceStateSchema,
|
|
73917
|
+
customize: powerSourceCustomize,
|
|
73918
|
+
/**
|
|
73919
|
+
* Runtime-state durability: **session** — mirrored from the linked switch on
|
|
73920
|
+
* its next report; a restored value would outlive the reading it names.
|
|
73921
|
+
*
|
|
73922
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
73923
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
73924
|
+
*/
|
|
73925
|
+
durability: "session",
|
|
73926
|
+
history: "none"
|
|
73927
|
+
};
|
|
73598
73928
|
/**
|
|
73599
73929
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
73600
73930
|
* on `DeviceType.Presence`. Read-only — no setters: presence is
|
|
@@ -77129,7 +77459,13 @@ var RemoteMediaCommandSchema = _enum([
|
|
|
77129
77459
|
"next",
|
|
77130
77460
|
"previous",
|
|
77131
77461
|
"setMute",
|
|
77132
|
-
"selectSource"
|
|
77462
|
+
"selectSource",
|
|
77463
|
+
"turnOn",
|
|
77464
|
+
"turnOff",
|
|
77465
|
+
"volumeUp",
|
|
77466
|
+
"volumeDown",
|
|
77467
|
+
"channelUp",
|
|
77468
|
+
"channelDown"
|
|
77133
77469
|
]);
|
|
77134
77470
|
/** A send result, or `not-routed`: the role is not bound, so the native cap answers. */
|
|
77135
77471
|
var RemoteMediaCommandResultSchema = discriminatedUnion("status", [...RemoteSendResultSchema.options, object({ status: literal("not-routed") })]);
|
|
@@ -77150,7 +77486,7 @@ method(deviceInput, RemoteConfigSchema, { auth: "admin" }), method(deviceInput.e
|
|
|
77150
77486
|
}), RemoteSendResultSchema, {
|
|
77151
77487
|
kind: "mutation",
|
|
77152
77488
|
auth: "protected"
|
|
77153
|
-
}), method(deviceInput.extend({
|
|
77489
|
+
}), method(deviceInput, MediaPlayerStatusSchema.nullable(), { auth: "protected" }), method(deviceInput.extend({
|
|
77154
77490
|
command: RemoteMediaCommandSchema,
|
|
77155
77491
|
muted: boolean().optional(),
|
|
77156
77492
|
source: string().optional(),
|
|
@@ -79434,7 +79770,11 @@ listSignals: method(_void(), array(StreamSignalSchema).readonly()) }
|
|
|
79434
79770
|
* `getSettingsUISchema()` surface.
|
|
79435
79771
|
*/
|
|
79436
79772
|
var SwitchStatusSchema = object({
|
|
79437
|
-
|
|
79773
|
+
/**
|
|
79774
|
+
* `null` = the device has never reported its state (a measurement that
|
|
79775
|
+
* has not happened is unknown, never `false`).
|
|
79776
|
+
*/
|
|
79777
|
+
on: boolean().nullable().meta({ label: "On" }),
|
|
79438
79778
|
/** Ms epoch of the last state change. Useful for UI "X minutes ago". */
|
|
79439
79779
|
lastChangedAt: number()
|
|
79440
79780
|
});
|
|
@@ -79459,7 +79799,7 @@ var switchCapability = {
|
|
|
79459
79799
|
}) },
|
|
79460
79800
|
events: { onStateChanged: { data: object({
|
|
79461
79801
|
deviceId: number(),
|
|
79462
|
-
on: boolean(),
|
|
79802
|
+
on: boolean().nullable(),
|
|
79463
79803
|
lastChangedAt: number()
|
|
79464
79804
|
}) } },
|
|
79465
79805
|
status: {
|
|
@@ -83062,6 +83402,26 @@ function buildEventKindDescriptor(kind, source) {
|
|
|
83062
83402
|
}
|
|
83063
83403
|
};
|
|
83064
83404
|
}
|
|
83405
|
+
/**
|
|
83406
|
+
* What a remote key is CALLED and what it LOOKS like, for every role (D963),
|
|
83407
|
+
* shared by the admin UI and the viewer. A role is data on the wire; each
|
|
83408
|
+
* client resolves its name from `label` (English and Italian side by side) and
|
|
83409
|
+
* its glyph from `icon`, a lucide id from the shared icon catalogue — the
|
|
83410
|
+
* server sends an id, a client maps it to its own icon set.
|
|
83411
|
+
*
|
|
83412
|
+
* `legend` is text printed on the key INSTEAD of a glyph (a digit has no
|
|
83413
|
+
* pictogram): a client that can draw text shows it, one that cannot falls back
|
|
83414
|
+
* to `icon`.
|
|
83415
|
+
*/
|
|
83416
|
+
function digit(n) {
|
|
83417
|
+
return {
|
|
83418
|
+
label: t(n, n),
|
|
83419
|
+
icon: "hash",
|
|
83420
|
+
legend: n
|
|
83421
|
+
};
|
|
83422
|
+
}
|
|
83423
|
+
digit("0"), digit("1"), digit("2"), digit("3"), digit("4"), digit("5"), digit("6"), digit("7"), digit("8"), digit("9");
|
|
83424
|
+
DeviceFeature.MediaPlayerPower, DeviceFeature.MediaPlayerVolumeStep, DeviceFeature.MediaPlayerChannelStep, DeviceFeature.MediaPlayerMute, DeviceFeature.MediaPlayerStop, DeviceFeature.MediaPlayerNext, DeviceFeature.MediaPlayerPrevious;
|
|
83065
83425
|
var btn = (idSuffix, row, col, init) => ({
|
|
83066
83426
|
idSuffix,
|
|
83067
83427
|
row,
|
|
@@ -83188,6 +83548,42 @@ discriminatedUnion("kind", [object({
|
|
|
83188
83548
|
kind: literal("pronto"),
|
|
83189
83549
|
code: string()
|
|
83190
83550
|
})]);
|
|
83551
|
+
/**
|
|
83552
|
+
* Propose a running threshold from a device's own power history (planning#405).
|
|
83553
|
+
*
|
|
83554
|
+
* Pure and deterministic: the same series gives the same answer. The series is
|
|
83555
|
+
* a HELD-VALUE step series — a point's value stands until the next point — which
|
|
83556
|
+
* is how device-history stores a gauge, so "time at a level" is exact, not a
|
|
83557
|
+
* count of samples.
|
|
83558
|
+
*
|
|
83559
|
+
* 1. idle floor F = time-weighted median; noise ceiling N = highest value seen
|
|
83560
|
+
* near F. A device that is not near one level most of the time has no floor.
|
|
83561
|
+
* 2. coarse activity = above max(2N, N + 5 W); consecutive stretches are episodes.
|
|
83562
|
+
* 3. an episode shorter than `PULSE_MAX_MS` is a PULSE (an anti-crease tumble, a
|
|
83563
|
+
* display waking): it is neither a run nor a pause. Among the remaining
|
|
83564
|
+
* episodes, gaps over `PAUSE_MAX_MS` always separate runs; the rest split in
|
|
83565
|
+
* two by the largest log-scale jump (>= 3x): the short ones are pauses INSIDE
|
|
83566
|
+
* a run (a soak), the long ones separate runs. A stretch under `MIN_RUN_MS`
|
|
83567
|
+
* is no run.
|
|
83568
|
+
* 4. T = geometric mean of N and the plateau's 10th percentile, snapped to a
|
|
83569
|
+
* grid a person would type; stop dwell covers the longest pause and the
|
|
83570
|
+
* kind's floor; start dwell covers the longest pulse and standby blip above T.
|
|
83571
|
+
* 5. the numbers are proved by REPLAY through the real `dwell` evaluation: each
|
|
83572
|
+
* run must hold exactly one true interval and nothing may flap outside.
|
|
83573
|
+
*/
|
|
83574
|
+
var SECOND_MS = 1e3;
|
|
83575
|
+
var MINUTE_MS$1 = 60 * SECOND_MS;
|
|
83576
|
+
24 * (60 * MINUTE_MS$1);
|
|
83577
|
+
10 * MINUTE_MS$1;
|
|
83578
|
+
30 * SECOND_MS;
|
|
83579
|
+
60 * SECOND_MS;
|
|
83580
|
+
20 * MINUTE_MS$1;
|
|
83581
|
+
90 * SECOND_MS;
|
|
83582
|
+
30 * MINUTE_MS$1;
|
|
83583
|
+
10 * MINUTE_MS$1;
|
|
83584
|
+
DeviceType.Dryer, 3 * MINUTE_MS$1, DeviceType.Dishwasher, 3 * MINUTE_MS$1, DeviceType.Washer, 10 * MINUTE_MS$1;
|
|
83585
|
+
10 * SECOND_MS;
|
|
83586
|
+
10 * SECOND_MS;
|
|
83191
83587
|
DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverStoppable, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
|
|
83192
83588
|
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
83193
83589
|
String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
|
|
@@ -85852,6 +86248,13 @@ Object.freeze({
|
|
|
85852
86248
|
access: "create",
|
|
85853
86249
|
role: "admin"
|
|
85854
86250
|
},
|
|
86251
|
+
"coreBlocks.proposeRunningThreshold": {
|
|
86252
|
+
capName: "core-blocks",
|
|
86253
|
+
capScope: "system",
|
|
86254
|
+
addonId: null,
|
|
86255
|
+
access: "view",
|
|
86256
|
+
role: "admin"
|
|
86257
|
+
},
|
|
85855
86258
|
"coreBlocks.reportAutomationRun": {
|
|
85856
86259
|
capName: "core-blocks",
|
|
85857
86260
|
capScope: "system",
|
|
@@ -86363,6 +86766,13 @@ Object.freeze({
|
|
|
86363
86766
|
access: "view",
|
|
86364
86767
|
role: "admin"
|
|
86365
86768
|
},
|
|
86769
|
+
"deviceExport.listInstances": {
|
|
86770
|
+
capName: "device-export",
|
|
86771
|
+
capScope: "system",
|
|
86772
|
+
addonId: null,
|
|
86773
|
+
access: "view",
|
|
86774
|
+
role: "admin"
|
|
86775
|
+
},
|
|
86366
86776
|
"deviceExport.listSupportedDeviceKinds": {
|
|
86367
86777
|
capName: "device-export",
|
|
86368
86778
|
capScope: "system",
|
|
@@ -88015,6 +88425,13 @@ Object.freeze({
|
|
|
88015
88425
|
access: "create",
|
|
88016
88426
|
role: "admin"
|
|
88017
88427
|
},
|
|
88428
|
+
"integrations.clearSettings": {
|
|
88429
|
+
capName: "integrations",
|
|
88430
|
+
capScope: "system",
|
|
88431
|
+
addonId: null,
|
|
88432
|
+
access: "delete",
|
|
88433
|
+
role: "admin"
|
|
88434
|
+
},
|
|
88018
88435
|
"integrations.create": {
|
|
88019
88436
|
capName: "integrations",
|
|
88020
88437
|
capScope: "system",
|
|
@@ -88799,6 +89216,20 @@ Object.freeze({
|
|
|
88799
89216
|
access: "view",
|
|
88800
89217
|
role: "admin"
|
|
88801
89218
|
},
|
|
89219
|
+
"mediaPlayer.channelDown": {
|
|
89220
|
+
capName: "media-player",
|
|
89221
|
+
capScope: "device",
|
|
89222
|
+
addonId: null,
|
|
89223
|
+
access: "create",
|
|
89224
|
+
role: "viewer"
|
|
89225
|
+
},
|
|
89226
|
+
"mediaPlayer.channelUp": {
|
|
89227
|
+
capName: "media-player",
|
|
89228
|
+
capScope: "device",
|
|
89229
|
+
addonId: null,
|
|
89230
|
+
access: "create",
|
|
89231
|
+
role: "viewer"
|
|
89232
|
+
},
|
|
88802
89233
|
"mediaPlayer.getStatus": {
|
|
88803
89234
|
capName: "media-player",
|
|
88804
89235
|
capScope: "device",
|
|
@@ -88890,6 +89321,34 @@ Object.freeze({
|
|
|
88890
89321
|
access: "create",
|
|
88891
89322
|
role: "viewer"
|
|
88892
89323
|
},
|
|
89324
|
+
"mediaPlayer.turnOff": {
|
|
89325
|
+
capName: "media-player",
|
|
89326
|
+
capScope: "device",
|
|
89327
|
+
addonId: null,
|
|
89328
|
+
access: "create",
|
|
89329
|
+
role: "viewer"
|
|
89330
|
+
},
|
|
89331
|
+
"mediaPlayer.turnOn": {
|
|
89332
|
+
capName: "media-player",
|
|
89333
|
+
capScope: "device",
|
|
89334
|
+
addonId: null,
|
|
89335
|
+
access: "create",
|
|
89336
|
+
role: "viewer"
|
|
89337
|
+
},
|
|
89338
|
+
"mediaPlayer.volumeDown": {
|
|
89339
|
+
capName: "media-player",
|
|
89340
|
+
capScope: "device",
|
|
89341
|
+
addonId: null,
|
|
89342
|
+
access: "create",
|
|
89343
|
+
role: "viewer"
|
|
89344
|
+
},
|
|
89345
|
+
"mediaPlayer.volumeUp": {
|
|
89346
|
+
capName: "media-player",
|
|
89347
|
+
capScope: "device",
|
|
89348
|
+
addonId: null,
|
|
89349
|
+
access: "create",
|
|
89350
|
+
role: "viewer"
|
|
89351
|
+
},
|
|
88893
89352
|
"meshNetwork.getStatus": {
|
|
88894
89353
|
capName: "mesh-network",
|
|
88895
89354
|
capScope: "system",
|
|
@@ -92446,6 +92905,13 @@ Object.freeze({
|
|
|
92446
92905
|
access: "create",
|
|
92447
92906
|
role: "admin"
|
|
92448
92907
|
},
|
|
92908
|
+
"remote.getAssumedStatus": {
|
|
92909
|
+
capName: "remote",
|
|
92910
|
+
capScope: "system",
|
|
92911
|
+
addonId: null,
|
|
92912
|
+
access: "view",
|
|
92913
|
+
role: "admin"
|
|
92914
|
+
},
|
|
92449
92915
|
"remote.getConfig": {
|
|
92450
92916
|
capName: "remote",
|
|
92451
92917
|
capScope: "system",
|
|
@@ -95261,6 +95727,11 @@ Object.freeze({
|
|
|
95261
95727
|
form: "single",
|
|
95262
95728
|
optional: false
|
|
95263
95729
|
}],
|
|
95730
|
+
"coreBlocks.proposeRunningThreshold": [{
|
|
95731
|
+
name: "deviceId",
|
|
95732
|
+
form: "single",
|
|
95733
|
+
optional: false
|
|
95734
|
+
}],
|
|
95264
95735
|
"cover.close": [{
|
|
95265
95736
|
name: "deviceId",
|
|
95266
95737
|
form: "single",
|
|
@@ -96112,6 +96583,16 @@ Object.freeze({
|
|
|
96112
96583
|
form: "single",
|
|
96113
96584
|
optional: true
|
|
96114
96585
|
}],
|
|
96586
|
+
"mediaPlayer.channelDown": [{
|
|
96587
|
+
name: "deviceId",
|
|
96588
|
+
form: "single",
|
|
96589
|
+
optional: false
|
|
96590
|
+
}],
|
|
96591
|
+
"mediaPlayer.channelUp": [{
|
|
96592
|
+
name: "deviceId",
|
|
96593
|
+
form: "single",
|
|
96594
|
+
optional: false
|
|
96595
|
+
}],
|
|
96115
96596
|
"mediaPlayer.getStatus": [{
|
|
96116
96597
|
name: "deviceId",
|
|
96117
96598
|
form: "single",
|
|
@@ -96177,6 +96658,26 @@ Object.freeze({
|
|
|
96177
96658
|
form: "single",
|
|
96178
96659
|
optional: false
|
|
96179
96660
|
}],
|
|
96661
|
+
"mediaPlayer.turnOff": [{
|
|
96662
|
+
name: "deviceId",
|
|
96663
|
+
form: "single",
|
|
96664
|
+
optional: false
|
|
96665
|
+
}],
|
|
96666
|
+
"mediaPlayer.turnOn": [{
|
|
96667
|
+
name: "deviceId",
|
|
96668
|
+
form: "single",
|
|
96669
|
+
optional: false
|
|
96670
|
+
}],
|
|
96671
|
+
"mediaPlayer.volumeDown": [{
|
|
96672
|
+
name: "deviceId",
|
|
96673
|
+
form: "single",
|
|
96674
|
+
optional: false
|
|
96675
|
+
}],
|
|
96676
|
+
"mediaPlayer.volumeUp": [{
|
|
96677
|
+
name: "deviceId",
|
|
96678
|
+
form: "single",
|
|
96679
|
+
optional: false
|
|
96680
|
+
}],
|
|
96180
96681
|
"meter.getStatus": [{
|
|
96181
96682
|
name: "deviceId",
|
|
96182
96683
|
form: "single",
|
|
@@ -97342,6 +97843,11 @@ Object.freeze({
|
|
|
97342
97843
|
form: "single",
|
|
97343
97844
|
optional: true
|
|
97344
97845
|
}],
|
|
97846
|
+
"remote.getAssumedStatus": [{
|
|
97847
|
+
name: "deviceId",
|
|
97848
|
+
form: "single",
|
|
97849
|
+
optional: false
|
|
97850
|
+
}],
|
|
97345
97851
|
"remote.getConfig": [{
|
|
97346
97852
|
name: "deviceId",
|
|
97347
97853
|
form: "single",
|
|
@@ -97986,99 +98492,6 @@ var BucketAccumulator = class {
|
|
|
97986
98492
|
return n;
|
|
97987
98493
|
}
|
|
97988
98494
|
};
|
|
97989
|
-
/**
|
|
97990
|
-
* A saved Customize assignment (D936). The schema is the type: callers use
|
|
97991
|
-
* `z.infer`, they do not restate the shape.
|
|
97992
|
-
*/
|
|
97993
|
-
var OverrideSourceSchema = object({
|
|
97994
|
-
addonId: string().min(1),
|
|
97995
|
-
stableId: string().min(1),
|
|
97996
|
-
cap: string().min(1),
|
|
97997
|
-
fieldPath: string().min(1)
|
|
97998
|
-
});
|
|
97999
|
-
var CustomizeTransformDraftSchema = discriminatedUnion("kind", [
|
|
98000
|
-
object({ kind: literal("identity") }),
|
|
98001
|
-
object({ kind: literal("invert") }),
|
|
98002
|
-
object({
|
|
98003
|
-
kind: literal("threshold"),
|
|
98004
|
-
comparison: _enum(["gte", "lte"]),
|
|
98005
|
-
threshold: number(),
|
|
98006
|
-
startDwellMs: number().nonnegative(),
|
|
98007
|
-
stopDwellMs: number().nonnegative()
|
|
98008
|
-
}),
|
|
98009
|
-
object({
|
|
98010
|
-
kind: literal("linear"),
|
|
98011
|
-
scale: number(),
|
|
98012
|
-
offset: number(),
|
|
98013
|
-
clampMin: number().optional(),
|
|
98014
|
-
clampMax: number().optional()
|
|
98015
|
-
}),
|
|
98016
|
-
object({
|
|
98017
|
-
kind: literal("enum-map"),
|
|
98018
|
-
mapping: record(string(), string().nullable())
|
|
98019
|
-
}),
|
|
98020
|
-
object({ kind: literal("number") })
|
|
98021
|
-
]);
|
|
98022
|
-
var ScalarOverrideDraftSchema = object({
|
|
98023
|
-
kind: literal("scalar"),
|
|
98024
|
-
cap: string().min(1),
|
|
98025
|
-
targetId: string().min(1),
|
|
98026
|
-
source: OverrideSourceSchema,
|
|
98027
|
-
transform: CustomizeTransformDraftSchema
|
|
98028
|
-
});
|
|
98029
|
-
var KeyedArrayOverrideDraftSchema = object({
|
|
98030
|
-
kind: literal("keyedArray"),
|
|
98031
|
-
cap: string().min(1),
|
|
98032
|
-
targetId: string().min(1),
|
|
98033
|
-
key: string().min(1),
|
|
98034
|
-
label: string().min(1),
|
|
98035
|
-
fieldPath: string().min(1),
|
|
98036
|
-
source: OverrideSourceSchema,
|
|
98037
|
-
transform: CustomizeTransformDraftSchema
|
|
98038
|
-
});
|
|
98039
|
-
var PulseOverrideDraftSchema = object({
|
|
98040
|
-
kind: literal("pulse"),
|
|
98041
|
-
cap: string().min(1),
|
|
98042
|
-
targetId: string().min(1),
|
|
98043
|
-
enabled: boolean(),
|
|
98044
|
-
debounceMs: number().nonnegative(),
|
|
98045
|
-
edges: array(_enum([
|
|
98046
|
-
"rising",
|
|
98047
|
-
"button",
|
|
98048
|
-
"native-event"
|
|
98049
|
-
])).min(1).optional(),
|
|
98050
|
-
sources: array(OverrideSourceSchema).min(1)
|
|
98051
|
-
});
|
|
98052
|
-
var SpanSourceDraftSchema = OverrideSourceSchema.extend({ mode: _enum([
|
|
98053
|
-
"in-addition",
|
|
98054
|
-
"confirm",
|
|
98055
|
-
"replace"
|
|
98056
|
-
]).optional() });
|
|
98057
|
-
discriminatedUnion("kind", [
|
|
98058
|
-
ScalarOverrideDraftSchema,
|
|
98059
|
-
KeyedArrayOverrideDraftSchema,
|
|
98060
|
-
PulseOverrideDraftSchema,
|
|
98061
|
-
object({
|
|
98062
|
-
kind: literal("span"),
|
|
98063
|
-
cap: string().min(1),
|
|
98064
|
-
targetId: string().min(1),
|
|
98065
|
-
timeoutMs: number().nonnegative(),
|
|
98066
|
-
cooldownMs: number().nonnegative().optional(),
|
|
98067
|
-
sources: array(SpanSourceDraftSchema)
|
|
98068
|
-
})
|
|
98069
|
-
]);
|
|
98070
|
-
object({
|
|
98071
|
-
targetId: string().min(1),
|
|
98072
|
-
configured: boolean(),
|
|
98073
|
-
source: _enum(["native", "assigned"]),
|
|
98074
|
-
state: _enum([
|
|
98075
|
-
"active",
|
|
98076
|
-
"stale",
|
|
98077
|
-
"released",
|
|
98078
|
-
"unavailable"
|
|
98079
|
-
]),
|
|
98080
|
-
reason: string().nullable()
|
|
98081
|
-
});
|
|
98082
98495
|
var G711_SCALE_CORRECTION_DB = {
|
|
98083
98496
|
PCMU: 20 * Math.log10(4),
|
|
98084
98497
|
PCMA: 20 * Math.log10(8)
|