@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
|
@@ -785,7 +785,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
785
785
|
return EventCategory;
|
|
786
786
|
}({});
|
|
787
787
|
//#endregion
|
|
788
|
-
//#region ../types/dist/device-type-
|
|
788
|
+
//#region ../types/dist/device-type-D1fH5kaC.mjs
|
|
789
789
|
/**
|
|
790
790
|
import { errMsg } from '@camstack/types'
|
|
791
791
|
* Extract a human-readable message from an unknown error value.
|
|
@@ -1016,6 +1016,12 @@ var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
|
|
|
1016
1016
|
DeviceFeature["MediaPlayerPrevious"] = "media-player-previous";
|
|
1017
1017
|
/** Media player exposes stop distinct from pause. */
|
|
1018
1018
|
DeviceFeature["MediaPlayerStop"] = "media-player-stop";
|
|
1019
|
+
/** Media player exposes volume up / down in steps (an infrared TV has no level). */
|
|
1020
|
+
DeviceFeature["MediaPlayerVolumeStep"] = "media-player-volume-step";
|
|
1021
|
+
/** Media player exposes channel up / down in steps. */
|
|
1022
|
+
DeviceFeature["MediaPlayerChannelStep"] = "media-player-channel-step";
|
|
1023
|
+
/** Media player exposes power on / off. */
|
|
1024
|
+
DeviceFeature["MediaPlayerPower"] = "media-player-power";
|
|
1019
1025
|
/** Alarm panel requires a PIN code on arm/disarm. */
|
|
1020
1026
|
DeviceFeature["AlarmPinRequired"] = "alarm-pin-required";
|
|
1021
1027
|
/** Presence device carries GPS coordinates (lat/lng/accuracy) in
|
|
@@ -6032,7 +6038,7 @@ var ZodIssueCode = {
|
|
|
6032
6038
|
var ZodFirstPartyTypeKind;
|
|
6033
6039
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
6034
6040
|
//#endregion
|
|
6035
|
-
//#region ../types/dist/sleep-
|
|
6041
|
+
//#region ../types/dist/sleep-D1jjWAr8.mjs
|
|
6036
6042
|
/**
|
|
6037
6043
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
6038
6044
|
* window to float samples (D455).
|
|
@@ -6625,7 +6631,7 @@ var NOT_RUN = {
|
|
|
6625
6631
|
* throws: an unreachable or refusing engine is logged and reported `declared: false`,
|
|
6626
6632
|
* because the hub (and this addon's boot) must not hang on a migration.
|
|
6627
6633
|
*/
|
|
6628
|
-
async function runAddonMigrations(host, migrations, logger) {
|
|
6634
|
+
async function runAddonMigrations(host, migrations, logger, options = {}) {
|
|
6629
6635
|
const first = migrations[0];
|
|
6630
6636
|
if (first === void 0) return NOT_RUN;
|
|
6631
6637
|
const owner = first.meta.owner;
|
|
@@ -6654,7 +6660,9 @@ async function runAddonMigrations(host, migrations, logger) {
|
|
|
6654
6660
|
else if (status === "blocked") blocked.push(id);
|
|
6655
6661
|
else skipped.push(id);
|
|
6656
6662
|
};
|
|
6663
|
+
const selected = options.only === void 0 ? null : new Set(options.only);
|
|
6657
6664
|
for (const step of declaration.steps) {
|
|
6665
|
+
if (selected !== null && !selected.has(step.id)) continue;
|
|
6658
6666
|
const bound = byId.get(step.id);
|
|
6659
6667
|
if (bound === void 0 || step.action === "skip") {
|
|
6660
6668
|
skipped.push(step.id);
|
|
@@ -7772,14 +7780,18 @@ var BaseAddon = class {
|
|
|
7772
7780
|
* nothing; the boot continues. A migration that FAILED (or was blocked by one)
|
|
7773
7781
|
* and declares `onFailure: 'block-owner'` makes this throw, so the addon does not
|
|
7774
7782
|
* serve data whose shape it cannot trust; `tolerate` migrations never do.
|
|
7783
|
+
*
|
|
7784
|
+
* ALWAYS pass the whole catalogue; a phase that must run only some of it passes
|
|
7785
|
+
* `{ only: [ids] }` — never a filtered catalogue (the engine would judge the
|
|
7786
|
+
* omitted applied ids "newer").
|
|
7775
7787
|
*/
|
|
7776
|
-
async runMigrations(migrations) {
|
|
7788
|
+
async runMigrations(migrations, options) {
|
|
7777
7789
|
const api = this.ctx.api.migrations;
|
|
7778
7790
|
const report = await runAddonMigrations({
|
|
7779
7791
|
declareOwner: (input) => api.declareOwner.mutate(input),
|
|
7780
7792
|
startMigration: (input) => api.startMigration.mutate(input),
|
|
7781
7793
|
finishMigration: (input) => api.finishMigration.mutate(input)
|
|
7782
|
-
}, migrations, this.ctx.logger);
|
|
7794
|
+
}, migrations, this.ctx.logger, options);
|
|
7783
7795
|
if (report.blockOwner.length > 0) throw new AddonMigrationsBlockedError(report.blockOwner);
|
|
7784
7796
|
return report;
|
|
7785
7797
|
}
|
|
@@ -8120,6 +8132,10 @@ var BaseAddon = class {
|
|
|
8120
8132
|
const stored = keychain ? await this.readAddonStoreWithRetry() : {};
|
|
8121
8133
|
const patch = {};
|
|
8122
8134
|
for (const key of keys) {
|
|
8135
|
+
if (tree.get(key)?.kind === "array") {
|
|
8136
|
+
patch[key] = [];
|
|
8137
|
+
continue;
|
|
8138
|
+
}
|
|
8123
8139
|
const keychainStored = tree.has(key) || collectSecretMarkerRefs(stored[key]).length > 0;
|
|
8124
8140
|
patch[key] = keychain && keychainStored ? SECRET_CLEAR : "";
|
|
8125
8141
|
}
|
|
@@ -8806,6 +8822,10 @@ var RECORD_SETTINGS_MAX_ROWS = 5e4;
|
|
|
8806
8822
|
* (`collectZodSecretPaths`): dotted keys, `[]` for "each element of this array"
|
|
8807
8823
|
* (`auth.accessToken`, `headers[].value`).
|
|
8808
8824
|
*
|
|
8825
|
+
* `{}` after a key means "each value of this map" (`applianceSecrets{}`): the map's own key
|
|
8826
|
+
* names the value (`applianceSecrets{fridge}`), so no id key is declared and a body that drops a
|
|
8827
|
+
* key releases exactly that key's secret.
|
|
8828
|
+
*
|
|
8809
8829
|
* Array elements are matched by a DECLARED id key (`secretArrayKeys`:
|
|
8810
8830
|
* `{ headers: 'name' }`), never by index, so reordering a list keeps every
|
|
8811
8831
|
* keychain ref (the same rule as `arrayItemFieldPath`). The concrete path of a
|
|
@@ -8818,11 +8838,13 @@ function parseSecretPath(path) {
|
|
|
8818
8838
|
if (path.length === 0) throw new InvalidRecordError("an empty secret path");
|
|
8819
8839
|
return path.split(".").map((raw) => {
|
|
8820
8840
|
const each = raw.endsWith("[]");
|
|
8821
|
-
const
|
|
8841
|
+
const map = raw.endsWith("{}");
|
|
8842
|
+
const key = each || map ? raw.slice(0, -2) : raw;
|
|
8822
8843
|
if (key.length === 0) throw new InvalidRecordError(`secret path "${path}" has an empty segment`);
|
|
8823
8844
|
return {
|
|
8824
8845
|
key,
|
|
8825
|
-
each
|
|
8846
|
+
each,
|
|
8847
|
+
map
|
|
8826
8848
|
};
|
|
8827
8849
|
});
|
|
8828
8850
|
}
|
|
@@ -8909,7 +8931,8 @@ function isZodSecret(schema) {
|
|
|
8909
8931
|
}
|
|
8910
8932
|
/**
|
|
8911
8933
|
* Every declared secret path in a config schema: dotted keys, `[]` for "each
|
|
8912
|
-
* element of this array" (`connection.password`, `rows[].token`)
|
|
8934
|
+
* element of this array" (`connection.password`, `rows[].token`), `{}` for "each value of this
|
|
8935
|
+
* map" (`applianceSecrets{}`). A declared
|
|
8913
8936
|
* object or array is reported as one path and not descended into — everything
|
|
8914
8937
|
* under it is secret.
|
|
8915
8938
|
*/
|
|
@@ -8920,6 +8943,7 @@ function collectZodSecretPaths(schema, prefix = "") {
|
|
|
8920
8943
|
const def = defOf(layer);
|
|
8921
8944
|
if (def.type === "object" && def.shape) for (const [key, child] of Object.entries(def.shape)) paths.push(...collectZodSecretPaths(child, prefix ? `${prefix}.${key}` : key));
|
|
8922
8945
|
else if (def.type === "array" && def.element) paths.push(...collectZodSecretPaths(def.element, `${prefix}[]`));
|
|
8946
|
+
else if (def.type === "record" && def.valueType) paths.push(...collectZodSecretPaths(def.valueType, `${prefix}{}`));
|
|
8923
8947
|
else if (def.type === "union" && def.options) for (const option of def.options) paths.push(...collectZodSecretPaths(option, prefix));
|
|
8924
8948
|
else if (def.type === "intersection") {
|
|
8925
8949
|
if (def.left) paths.push(...collectZodSecretPaths(def.left, prefix));
|
|
@@ -9059,7 +9083,7 @@ function defineRecordKinds(specs) {
|
|
|
9059
9083
|
retention: spec.retention,
|
|
9060
9084
|
deviceRemoval: spec.deviceRemoval,
|
|
9061
9085
|
maxDataBytes: spec.maxDataBytes,
|
|
9062
|
-
secretPaths: [...secretPaths],
|
|
9086
|
+
secretPaths: [...new Set([...secretPaths, ...spec.retiredSecretPaths ?? []])],
|
|
9063
9087
|
secretArrayKeys: spec.secretArrayKeys === void 0 ? void 0 : { ...spec.secretArrayKeys },
|
|
9064
9088
|
transactFamily: spec.transactFamily,
|
|
9065
9089
|
entry: spec.entry === void 0 ? void 0 : {
|
|
@@ -11968,7 +11992,7 @@ function sleep(ms) {
|
|
|
11968
11992
|
return new Promise((resolve) => setTimeout(resolve, Math.max(0, ms)));
|
|
11969
11993
|
}
|
|
11970
11994
|
//#endregion
|
|
11971
|
-
//#region ../types/dist/composition-
|
|
11995
|
+
//#region ../types/dist/composition-pOHbTzRB.mjs
|
|
11972
11996
|
/**
|
|
11973
11997
|
* Deterministic SHA-256 hash of an arbitrary serialisable value. The
|
|
11974
11998
|
* canonical form sorts object keys alphabetically at every depth so two
|
|
@@ -12891,38 +12915,6 @@ function validateExpressionSource(src) {
|
|
|
12891
12915
|
return null;
|
|
12892
12916
|
}
|
|
12893
12917
|
/**
|
|
12894
|
-
* One power reading becomes a washer, dryer or dishwasher (D944 helper).
|
|
12895
|
-
*
|
|
12896
|
-
* Standby of the control board is under 5 W; a motor or a heater is far
|
|
12897
|
-
* above that, so 5 W is the line. A door lock or a short pump spike is not
|
|
12898
|
-
* a cycle, so running starts only after 30 s above the line.
|
|
12899
|
-
*
|
|
12900
|
-
* A wash, dry or dishwasher pause (soak, heat-wait, heater off between
|
|
12901
|
-
* bursts) lasts several minutes. Ending the cycle on the first dip would
|
|
12902
|
-
* report "finished" in the middle of the program, so the stop dwell is
|
|
12903
|
-
* 10 minutes on every type. The number is stored per type so one machine
|
|
12904
|
-
* can move later without moving the others.
|
|
12905
|
-
*/
|
|
12906
|
-
var APPLIANCE_TEMPLATE_ID = "appliance";
|
|
12907
|
-
var APPLIANCE_KINDS = [
|
|
12908
|
-
"washer",
|
|
12909
|
-
"dryer",
|
|
12910
|
-
"dishwasher"
|
|
12911
|
-
];
|
|
12912
|
-
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
|
|
12913
|
-
/**
|
|
12914
|
-
* A dumb plug-in stove or heater, built from a smart plug (a `Heater`).
|
|
12915
|
-
*
|
|
12916
|
-
* The plug is the actuator: `switch.setState` is a FORWARD to the plug's own
|
|
12917
|
-
* (D967), so the heater switches exactly as the plug does. Running is the
|
|
12918
|
-
* plug being on; when a power reading is also named, running is the draw
|
|
12919
|
-
* staying above the line instead (a plug left on with the stove's own
|
|
12920
|
-
* thermostat open is not heating). 50 W is far above any standby and below
|
|
12921
|
-
* the smallest radiator.
|
|
12922
|
-
*/
|
|
12923
|
-
var HEATER_TEMPLATE_ID = "heater";
|
|
12924
|
-
DeviceType.Heater;
|
|
12925
|
-
/**
|
|
12926
12918
|
* Statistics and integrals over a history read (D944).
|
|
12927
12919
|
*
|
|
12928
12920
|
* Pure: the same points always give the same answer, so a restart recomputes
|
|
@@ -13066,34 +13058,6 @@ var HelperSpecSchema = discriminatedUnion("kind", [
|
|
|
13066
13058
|
/** Actuator groups only. Readings leave this unset. */
|
|
13067
13059
|
active: ActiveCriterionSchema.optional()
|
|
13068
13060
|
}),
|
|
13069
|
-
object({
|
|
13070
|
-
kind: literal("appliance"),
|
|
13071
|
-
templateId: literal(APPLIANCE_TEMPLATE_ID),
|
|
13072
|
-
appliance: _enum(APPLIANCE_KINDS),
|
|
13073
|
-
thresholdWatts: number().positive(),
|
|
13074
|
-
startDwellMs: number().int().nonnegative(),
|
|
13075
|
-
stopDwellMs: number().int().nonnegative(),
|
|
13076
|
-
member: HelperMemberSchema,
|
|
13077
|
-
/**
|
|
13078
|
-
* The plug that powers the appliance (`switch.on`). Optional: when set, the
|
|
13079
|
-
* composition carries a `power-source` feature, so the hub can cut and restore
|
|
13080
|
-
* that plug (power-source link of a NEW-target composition).
|
|
13081
|
-
*/
|
|
13082
|
-
powerSwitch: HelperMemberSchema.optional(),
|
|
13083
|
-
/** How long a forced restart keeps the plug off; the cap's default when unset. */
|
|
13084
|
-
offSeconds: number().optional()
|
|
13085
|
-
}),
|
|
13086
|
-
object({
|
|
13087
|
-
kind: literal("heater"),
|
|
13088
|
-
templateId: literal(HEATER_TEMPLATE_ID),
|
|
13089
|
-
/** The plug, read and commanded at `switch.on`. */
|
|
13090
|
-
plug: HelperMemberSchema,
|
|
13091
|
-
/** The plug's power reading, when it has one: running is then the draw, not the switch. */
|
|
13092
|
-
meter: HelperMemberSchema.optional(),
|
|
13093
|
-
thresholdWatts: number().positive(),
|
|
13094
|
-
startDwellMs: number().int().nonnegative(),
|
|
13095
|
-
stopDwellMs: number().int().nonnegative()
|
|
13096
|
-
}),
|
|
13097
13061
|
object({
|
|
13098
13062
|
kind: literal("statistic"),
|
|
13099
13063
|
stat: _enum(STATISTIC_STATS),
|
|
@@ -13265,7 +13229,14 @@ var CompositionForwardCommandSchema = object({
|
|
|
13265
13229
|
method: string().min(1),
|
|
13266
13230
|
args: record(string().min(1), CompositionForwardArgSchema).optional()
|
|
13267
13231
|
});
|
|
13268
|
-
var CompositionCommandTargetSchema = discriminatedUnion("kind", [
|
|
13232
|
+
var CompositionCommandTargetSchema = discriminatedUnion("kind", [
|
|
13233
|
+
CompositionForwardCommandSchema,
|
|
13234
|
+
CompositionCodeSourceSchema,
|
|
13235
|
+
object({
|
|
13236
|
+
kind: literal("extension"),
|
|
13237
|
+
target: literal("remote")
|
|
13238
|
+
})
|
|
13239
|
+
]);
|
|
13269
13240
|
/** An item key inside an item-array cap (`consumables.items[<key>]`). */
|
|
13270
13241
|
var COMPOSITION_ITEM_KEY_RE = /^[a-z0-9][a-z0-9-]{0,47}$/;
|
|
13271
13242
|
/**
|
|
@@ -13310,7 +13281,7 @@ var CompositionSchema = object({
|
|
|
13310
13281
|
kind: literal("existing"),
|
|
13311
13282
|
device: CompositionSourceRefSchema
|
|
13312
13283
|
})]),
|
|
13313
|
-
features: array(CompositionFeatureSchema).min(
|
|
13284
|
+
features: array(CompositionFeatureSchema).min(0).max(16),
|
|
13314
13285
|
/**
|
|
13315
13286
|
* Present when the block is a helper template. Absent on a free
|
|
13316
13287
|
* composition (the room example, device 4603). The editor reads this,
|
|
@@ -14690,7 +14661,13 @@ var MigrationLedgerEntrySchema = object({
|
|
|
14690
14661
|
* joined by the engine from the catalogues it knows this boot. Absent when no
|
|
14691
14662
|
* catalogue lists the id (a newer database).
|
|
14692
14663
|
*/
|
|
14693
|
-
meta: MigrationMetaSchema.optional()
|
|
14664
|
+
meta: MigrationMetaSchema.optional(),
|
|
14665
|
+
/**
|
|
14666
|
+
* Set when this is an applied row of an addon owner whose catalogue the answering
|
|
14667
|
+
* process has not loaded (the owner has not declared yet): the row is applied, the
|
|
14668
|
+
* process just cannot judge it. Never `skipped-newer` — that needs the owner loaded.
|
|
14669
|
+
*/
|
|
14670
|
+
ownerNotLoaded: boolean().optional()
|
|
14694
14671
|
});
|
|
14695
14672
|
/** A catalogued migration that is not applied, with where it stands. */
|
|
14696
14673
|
var MigrationPendingEntrySchema = object({
|
|
@@ -20532,6 +20509,48 @@ var APPLIANCE_CAP_VOCABULARY = {
|
|
|
20532
20509
|
scope: "device",
|
|
20533
20510
|
noun: t("Media player", "Lettore multimediale"),
|
|
20534
20511
|
actions: [
|
|
20512
|
+
{
|
|
20513
|
+
id: "media.turnOn",
|
|
20514
|
+
method: "turnOn",
|
|
20515
|
+
label: t("Turn on", "Accendi"),
|
|
20516
|
+
phrase: t("Turn on {device}", "Accendi {device}"),
|
|
20517
|
+
icon: "power"
|
|
20518
|
+
},
|
|
20519
|
+
{
|
|
20520
|
+
id: "media.turnOff",
|
|
20521
|
+
method: "turnOff",
|
|
20522
|
+
label: t("Turn off", "Spegni"),
|
|
20523
|
+
phrase: t("Turn off {device}", "Spegni {device}"),
|
|
20524
|
+
icon: "power"
|
|
20525
|
+
},
|
|
20526
|
+
{
|
|
20527
|
+
id: "media.volumeUp",
|
|
20528
|
+
method: "volumeUp",
|
|
20529
|
+
label: t("Volume up", "Alza il volume"),
|
|
20530
|
+
phrase: t("Raise the volume of {device}", "Alza il volume di {device}"),
|
|
20531
|
+
icon: "volume-2"
|
|
20532
|
+
},
|
|
20533
|
+
{
|
|
20534
|
+
id: "media.volumeDown",
|
|
20535
|
+
method: "volumeDown",
|
|
20536
|
+
label: t("Volume down", "Abbassa il volume"),
|
|
20537
|
+
phrase: t("Lower the volume of {device}", "Abbassa il volume di {device}"),
|
|
20538
|
+
icon: "volume-2"
|
|
20539
|
+
},
|
|
20540
|
+
{
|
|
20541
|
+
id: "media.channelUp",
|
|
20542
|
+
method: "channelUp",
|
|
20543
|
+
label: t("Channel up", "Canale successivo"),
|
|
20544
|
+
phrase: t("Go to the next channel on {device}", "Passa al canale successivo su {device}"),
|
|
20545
|
+
icon: "skip-forward"
|
|
20546
|
+
},
|
|
20547
|
+
{
|
|
20548
|
+
id: "media.channelDown",
|
|
20549
|
+
method: "channelDown",
|
|
20550
|
+
label: t("Channel down", "Canale precedente"),
|
|
20551
|
+
phrase: t("Go to the previous channel on {device}", "Torna al canale precedente su {device}"),
|
|
20552
|
+
icon: "skip-back"
|
|
20553
|
+
},
|
|
20535
20554
|
{
|
|
20536
20555
|
id: "media.play",
|
|
20537
20556
|
method: "play",
|
|
@@ -50334,6 +50353,244 @@ var controlCapability = {
|
|
|
50334
50353
|
*/
|
|
50335
50354
|
history: "none"
|
|
50336
50355
|
};
|
|
50356
|
+
/**
|
|
50357
|
+
* Media-player cap. Models HA `media_player.*` (Sonos, Chromecast,
|
|
50358
|
+
* Apple TV, Spotify, Roku, generic OTT receivers, …) on
|
|
50359
|
+
* `DeviceType.MediaPlayer`. Disjoint from the camera streaming
|
|
50360
|
+
* surface — those use `DeviceType.Camera` + the broker pipeline.
|
|
50361
|
+
*
|
|
50362
|
+
* The cap declares a wide method surface; not every backend supports
|
|
50363
|
+
* every method. Drivers signal sub-capability via the
|
|
50364
|
+
* `DeviceFeature.MediaPlayerXxx` flags (paired one-to-one with the
|
|
50365
|
+
* corresponding method) so the UI gates buttons without a slice
|
|
50366
|
+
* fetch — same pattern as `PanTiltZoom` for cameras.
|
|
50367
|
+
*/
|
|
50368
|
+
var MediaPlayerStateSchema = _enum([
|
|
50369
|
+
"off",
|
|
50370
|
+
"on",
|
|
50371
|
+
"idle",
|
|
50372
|
+
"playing",
|
|
50373
|
+
"paused",
|
|
50374
|
+
"buffering",
|
|
50375
|
+
"standby"
|
|
50376
|
+
]);
|
|
50377
|
+
var MediaPlayerRepeatSchema = _enum([
|
|
50378
|
+
"off",
|
|
50379
|
+
"all",
|
|
50380
|
+
"one"
|
|
50381
|
+
]);
|
|
50382
|
+
var MediaInfoSchema = object({
|
|
50383
|
+
/** Free-form media kind (`music`, `tvshow`, `movie`, `app`, `channel`,
|
|
50384
|
+
* `podcast`, …). */
|
|
50385
|
+
type: string(),
|
|
50386
|
+
/** Human-readable title. */
|
|
50387
|
+
title: string(),
|
|
50388
|
+
/** Optional artist / channel / station label. */
|
|
50389
|
+
artist: string().optional(),
|
|
50390
|
+
/** Optional album / season / show name. */
|
|
50391
|
+
album: string().optional(),
|
|
50392
|
+
/** Optional cover-art / thumbnail URL. */
|
|
50393
|
+
imageUrl: string().optional()
|
|
50394
|
+
});
|
|
50395
|
+
/**
|
|
50396
|
+
* Where `state`, `volumeLevel`, `isMuted` and `source` come from. `reported`:
|
|
50397
|
+
* the device said so. `assumed`: the driver has no feedback (infrared) and
|
|
50398
|
+
* tracks what it last SENT; it moves only after a send was accepted, and a
|
|
50399
|
+
* human at the real remote makes it wrong. A UI shows an assumed value as a
|
|
50400
|
+
* guess, never as a reading.
|
|
50401
|
+
*/
|
|
50402
|
+
var MediaPlayerStateSourceSchema = _enum(["reported", "assumed"]);
|
|
50403
|
+
/** The fields of a media-player status a driver can only guess. */
|
|
50404
|
+
var MediaPlayerAssumedFieldSchema = _enum([
|
|
50405
|
+
"state",
|
|
50406
|
+
"volumeLevel",
|
|
50407
|
+
"isMuted",
|
|
50408
|
+
"source"
|
|
50409
|
+
]);
|
|
50410
|
+
var MediaPlayerStatusSchema = object({
|
|
50411
|
+
/** Playback lifecycle state. */
|
|
50412
|
+
state: MediaPlayerStateSchema,
|
|
50413
|
+
/**
|
|
50414
|
+
* Whether the state fields are readings or the driver's own bookkeeping.
|
|
50415
|
+
* A slice written before this field existed parses as `reported`.
|
|
50416
|
+
*/
|
|
50417
|
+
stateSource: MediaPlayerStateSourceSchema.default("reported"),
|
|
50418
|
+
/**
|
|
50419
|
+
* Which fields are the driver's own guess. `stateSource` is `assumed` when
|
|
50420
|
+
* this is not empty; a field not listed here is a reading even then (power
|
|
50421
|
+
* from a running-state source, mute guessed from the last send).
|
|
50422
|
+
*/
|
|
50423
|
+
assumedFields: array(MediaPlayerAssumedFieldSchema).default([]),
|
|
50424
|
+
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
50425
|
+
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
50426
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
50427
|
+
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
50428
|
+
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
50429
|
+
isMuted: boolean().nullable(),
|
|
50430
|
+
/** Active source / input. Empty when no source surface. */
|
|
50431
|
+
source: string(),
|
|
50432
|
+
/** Selectable sources. Empty when no source surface.
|
|
50433
|
+
* Pair with `DeviceFeature.MediaPlayerSelectSource`. */
|
|
50434
|
+
availableSources: array(string()),
|
|
50435
|
+
/** Currently-playing media info. Null when nothing is playing. */
|
|
50436
|
+
currentMedia: MediaInfoSchema.nullable(),
|
|
50437
|
+
/** Current playback position in ms. Null when not seekable or
|
|
50438
|
+
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
50439
|
+
position: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
50440
|
+
/** Total duration of the current media in ms. Null when unknown
|
|
50441
|
+
* (live stream) or nothing is playing. */
|
|
50442
|
+
duration: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
50443
|
+
/** Shuffle toggle. Null when no shuffle surface.
|
|
50444
|
+
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
50445
|
+
shuffle: boolean().nullable(),
|
|
50446
|
+
/** Repeat mode. Null when no repeat surface.
|
|
50447
|
+
* Pair with `DeviceFeature.MediaPlayerRepeat`. */
|
|
50448
|
+
repeat: MediaPlayerRepeatSchema.nullable(),
|
|
50449
|
+
/** Ms epoch when the slice was last updated. */
|
|
50450
|
+
lastChangedAt: number()
|
|
50451
|
+
});
|
|
50452
|
+
var stepInput = object({
|
|
50453
|
+
deviceId: number().int().nonnegative(),
|
|
50454
|
+
/** How many presses: the caller's count (Alexa `volumeSteps`, `channelCount`). */
|
|
50455
|
+
steps: number().int().min(1).max(50).default(1)
|
|
50456
|
+
});
|
|
50457
|
+
var deviceOnly = object({ deviceId: number().int().nonnegative() });
|
|
50458
|
+
var mediaPlayerCapability = {
|
|
50459
|
+
name: "media-player",
|
|
50460
|
+
scope: "device",
|
|
50461
|
+
deviceNative: true,
|
|
50462
|
+
mode: "singleton",
|
|
50463
|
+
deviceTypes: [DeviceType.MediaPlayer],
|
|
50464
|
+
methods: {
|
|
50465
|
+
turnOn: method(deviceOnly, _void(), {
|
|
50466
|
+
kind: "mutation",
|
|
50467
|
+
auth: "protected"
|
|
50468
|
+
}),
|
|
50469
|
+
turnOff: method(deviceOnly, _void(), {
|
|
50470
|
+
kind: "mutation",
|
|
50471
|
+
auth: "protected"
|
|
50472
|
+
}),
|
|
50473
|
+
volumeUp: method(stepInput, _void(), {
|
|
50474
|
+
kind: "mutation",
|
|
50475
|
+
auth: "protected"
|
|
50476
|
+
}),
|
|
50477
|
+
volumeDown: method(stepInput, _void(), {
|
|
50478
|
+
kind: "mutation",
|
|
50479
|
+
auth: "protected"
|
|
50480
|
+
}),
|
|
50481
|
+
channelUp: method(stepInput, _void(), {
|
|
50482
|
+
kind: "mutation",
|
|
50483
|
+
auth: "protected"
|
|
50484
|
+
}),
|
|
50485
|
+
channelDown: method(stepInput, _void(), {
|
|
50486
|
+
kind: "mutation",
|
|
50487
|
+
auth: "protected"
|
|
50488
|
+
}),
|
|
50489
|
+
play: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
50490
|
+
kind: "mutation",
|
|
50491
|
+
auth: "protected"
|
|
50492
|
+
}),
|
|
50493
|
+
pause: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
50494
|
+
kind: "mutation",
|
|
50495
|
+
auth: "protected"
|
|
50496
|
+
}),
|
|
50497
|
+
stop: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
50498
|
+
kind: "mutation",
|
|
50499
|
+
auth: "protected"
|
|
50500
|
+
}),
|
|
50501
|
+
next: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
50502
|
+
kind: "mutation",
|
|
50503
|
+
auth: "protected"
|
|
50504
|
+
}),
|
|
50505
|
+
previous: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
50506
|
+
kind: "mutation",
|
|
50507
|
+
auth: "protected"
|
|
50508
|
+
}),
|
|
50509
|
+
seek: method(object({
|
|
50510
|
+
deviceId: number().int().nonnegative(),
|
|
50511
|
+
position: number().int().nonnegative()
|
|
50512
|
+
}), _void(), {
|
|
50513
|
+
kind: "mutation",
|
|
50514
|
+
auth: "protected"
|
|
50515
|
+
}),
|
|
50516
|
+
setVolume: method(object({
|
|
50517
|
+
deviceId: number().int().nonnegative(),
|
|
50518
|
+
volumeLevel: number().min(0).max(100)
|
|
50519
|
+
}), _void(), {
|
|
50520
|
+
kind: "mutation",
|
|
50521
|
+
auth: "protected"
|
|
50522
|
+
}),
|
|
50523
|
+
setMute: method(object({
|
|
50524
|
+
deviceId: number().int().nonnegative(),
|
|
50525
|
+
muted: boolean()
|
|
50526
|
+
}), _void(), {
|
|
50527
|
+
kind: "mutation",
|
|
50528
|
+
auth: "protected"
|
|
50529
|
+
}),
|
|
50530
|
+
setShuffle: method(object({
|
|
50531
|
+
deviceId: number().int().nonnegative(),
|
|
50532
|
+
shuffle: boolean()
|
|
50533
|
+
}), _void(), {
|
|
50534
|
+
kind: "mutation",
|
|
50535
|
+
auth: "protected"
|
|
50536
|
+
}),
|
|
50537
|
+
setRepeat: method(object({
|
|
50538
|
+
deviceId: number().int().nonnegative(),
|
|
50539
|
+
repeat: MediaPlayerRepeatSchema
|
|
50540
|
+
}), _void(), {
|
|
50541
|
+
kind: "mutation",
|
|
50542
|
+
auth: "protected"
|
|
50543
|
+
}),
|
|
50544
|
+
selectSource: method(object({
|
|
50545
|
+
deviceId: number().int().nonnegative(),
|
|
50546
|
+
source: string().min(1)
|
|
50547
|
+
}), _void(), {
|
|
50548
|
+
kind: "mutation",
|
|
50549
|
+
auth: "protected"
|
|
50550
|
+
}),
|
|
50551
|
+
playMedia: method(object({
|
|
50552
|
+
deviceId: number().int().nonnegative(),
|
|
50553
|
+
/** Media identifier / URL. */
|
|
50554
|
+
mediaId: string().min(1),
|
|
50555
|
+
/** Media kind (`music`, `tvshow`, `movie`, `app`, …) — provider
|
|
50556
|
+
* passes it through to the upstream service. */
|
|
50557
|
+
mediaType: string().min(1)
|
|
50558
|
+
}), _void(), {
|
|
50559
|
+
kind: "mutation",
|
|
50560
|
+
auth: "protected"
|
|
50561
|
+
})
|
|
50562
|
+
},
|
|
50563
|
+
status: {
|
|
50564
|
+
schema: MediaPlayerStatusSchema,
|
|
50565
|
+
kind: "push"
|
|
50566
|
+
},
|
|
50567
|
+
/**
|
|
50568
|
+
* Runtime-state slice — mirrored by the kernel. UI players read the
|
|
50569
|
+
* full slice for live now-playing, volume, and progress updates
|
|
50570
|
+
* without polling.
|
|
50571
|
+
*/
|
|
50572
|
+
runtimeState: MediaPlayerStatusSchema,
|
|
50573
|
+
/**
|
|
50574
|
+
* Runtime-state durability: **session** — a restored transport position describes a playback that stopped when the hub did.
|
|
50575
|
+
*
|
|
50576
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
50577
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
50578
|
+
*/
|
|
50579
|
+
durability: "session",
|
|
50580
|
+
/**
|
|
50581
|
+
* History (D850): volume (a level an operator or an automation sets; the
|
|
50582
|
+
* default 10 s floor folds a slider drag into its end value) and mute.
|
|
50583
|
+
* `position` is not recorded: it moves continuously while playing.
|
|
50584
|
+
*/
|
|
50585
|
+
history: { fields: {
|
|
50586
|
+
volumeLevel: {
|
|
50587
|
+
kind: "gauge",
|
|
50588
|
+
unit: "%",
|
|
50589
|
+
deadband: 1
|
|
50590
|
+
},
|
|
50591
|
+
isMuted: { kind: "boolean" }
|
|
50592
|
+
} }
|
|
50593
|
+
};
|
|
50337
50594
|
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;
|
|
50338
50595
|
var NUMBER = {
|
|
50339
50596
|
kind: "fixed",
|
|
@@ -50781,117 +51038,6 @@ function actuator(input) {
|
|
|
50781
51038
|
};
|
|
50782
51039
|
}
|
|
50783
51040
|
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
50784
|
-
var PowerSourceRefusalReasonSchema = _enum([
|
|
50785
|
-
"no-power-source",
|
|
50786
|
-
"switch-missing",
|
|
50787
|
-
"switch-offline",
|
|
50788
|
-
"switch-unknown",
|
|
50789
|
-
"restart-in-progress",
|
|
50790
|
-
"switch-call-failed"
|
|
50791
|
-
]);
|
|
50792
|
-
var PowerSourceActionResultSchema = discriminatedUnion("accepted", [object({ accepted: literal(true) }), object({
|
|
50793
|
-
accepted: literal(false),
|
|
50794
|
-
reason: PowerSourceRefusalReasonSchema,
|
|
50795
|
-
/** One line for the operator, naming the switch. */
|
|
50796
|
-
message: string()
|
|
50797
|
-
})]);
|
|
50798
|
-
var PowerSourceInfoSchema = object({
|
|
50799
|
-
/** False when the device has no power source linked; the rest is then empty. */
|
|
50800
|
-
linked: boolean(),
|
|
50801
|
-
switchDeviceId: number().nullable(),
|
|
50802
|
-
switchName: string().nullable(),
|
|
50803
|
-
/** The switch's on/off state, or null when it is unknown. Never false for unknown (D393). */
|
|
50804
|
-
switchOn: boolean().nullable(),
|
|
50805
|
-
switchOnline: boolean().nullable(),
|
|
50806
|
-
restartInProgress: boolean(),
|
|
50807
|
-
offSeconds: number().int()
|
|
50808
|
-
});
|
|
50809
|
-
/** The composed slice: the switch state the link mirrors, plus the stored off time. */
|
|
50810
|
-
var PowerSourceStateSchema = object({
|
|
50811
|
-
/** Null while the switch has not reported: unknown is never `false` (D393). */
|
|
50812
|
-
switchOn: boolean().nullable(),
|
|
50813
|
-
offSeconds: number().int(),
|
|
50814
|
-
lastFetchedAt: number()
|
|
50815
|
-
});
|
|
50816
|
-
var POWER_SOURCE_DEVICE_TYPES = [
|
|
50817
|
-
DeviceType.Gateway,
|
|
50818
|
-
DeviceType.Hub,
|
|
50819
|
-
DeviceType.Camera,
|
|
50820
|
-
DeviceType.Sensor,
|
|
50821
|
-
DeviceType.MediaPlayer,
|
|
50822
|
-
DeviceType.Vacuum,
|
|
50823
|
-
DeviceType.Generic,
|
|
50824
|
-
DeviceType.Washer,
|
|
50825
|
-
DeviceType.Dryer,
|
|
50826
|
-
DeviceType.Dishwasher,
|
|
50827
|
-
DeviceType.PetFountain,
|
|
50828
|
-
DeviceType.Fan,
|
|
50829
|
-
DeviceType.Humidifier,
|
|
50830
|
-
DeviceType.Climate,
|
|
50831
|
-
DeviceType.WaterHeater
|
|
50832
|
-
];
|
|
50833
|
-
var powerSourceCustomize = {
|
|
50834
|
-
version: 1,
|
|
50835
|
-
targets: [{
|
|
50836
|
-
id: "switch",
|
|
50837
|
-
cardinality: "scalar",
|
|
50838
|
-
vocabulary: {
|
|
50839
|
-
cap: "power-source",
|
|
50840
|
-
stateField: "switchOn"
|
|
50841
|
-
},
|
|
50842
|
-
deviceTypes: POWER_SOURCE_DEVICE_TYPES,
|
|
50843
|
-
apply: "add",
|
|
50844
|
-
path: "switchOn",
|
|
50845
|
-
sources: [{
|
|
50846
|
-
kind: "switch",
|
|
50847
|
-
transforms: [{ kind: "identity" }]
|
|
50848
|
-
}],
|
|
50849
|
-
companions: [{
|
|
50850
|
-
kind: "constant",
|
|
50851
|
-
path: "offSeconds",
|
|
50852
|
-
value: 10,
|
|
50853
|
-
when: "add"
|
|
50854
|
-
}, {
|
|
50855
|
-
kind: "clock",
|
|
50856
|
-
path: "lastFetchedAt",
|
|
50857
|
-
when: "always"
|
|
50858
|
-
}],
|
|
50859
|
-
sourceReport: { status: "assignment-status" }
|
|
50860
|
-
}]
|
|
50861
|
-
};
|
|
50862
|
-
var deviceInput$2 = object({ deviceId: number().int().nonnegative() });
|
|
50863
|
-
var powerSourceCapability = {
|
|
50864
|
-
name: "power-source",
|
|
50865
|
-
scope: "device",
|
|
50866
|
-
mode: "singleton",
|
|
50867
|
-
deviceTypes: POWER_SOURCE_DEVICE_TYPES,
|
|
50868
|
-
methods: {
|
|
50869
|
-
getStatus: systemMethod(deviceInput$2, PowerSourceInfoSchema, { auth: "admin" }),
|
|
50870
|
-
powerOn: systemMethod(deviceInput$2, PowerSourceActionResultSchema, {
|
|
50871
|
-
kind: "mutation",
|
|
50872
|
-
auth: "admin"
|
|
50873
|
-
}),
|
|
50874
|
-
powerOff: systemMethod(deviceInput$2, PowerSourceActionResultSchema, {
|
|
50875
|
-
kind: "mutation",
|
|
50876
|
-
auth: "admin"
|
|
50877
|
-
}),
|
|
50878
|
-
forceRestart: systemMethod(deviceInput$2, PowerSourceActionResultSchema, {
|
|
50879
|
-
kind: "mutation",
|
|
50880
|
-
auth: "admin"
|
|
50881
|
-
})
|
|
50882
|
-
},
|
|
50883
|
-
runtimeState: PowerSourceStateSchema,
|
|
50884
|
-
customize: powerSourceCustomize,
|
|
50885
|
-
/**
|
|
50886
|
-
* Runtime-state durability: **session** — mirrored from the linked switch on
|
|
50887
|
-
* its next report; a restored value would outlive the reading it names.
|
|
50888
|
-
*
|
|
50889
|
-
* See `RuntimeStateDurability`. Enforced by
|
|
50890
|
-
* `scripts/check-runtime-state-durability.ts`.
|
|
50891
|
-
*/
|
|
50892
|
-
durability: "session",
|
|
50893
|
-
history: "none"
|
|
50894
|
-
};
|
|
50895
51041
|
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
50896
51042
|
DeviceType.Camera;
|
|
50897
51043
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
@@ -50919,6 +51065,168 @@ var ComposableCapabilitiesSchema = object({ caps: array(object({
|
|
|
50919
51065
|
}).optional()
|
|
50920
51066
|
})) });
|
|
50921
51067
|
/**
|
|
51068
|
+
* A saved Customize assignment (D936). The schema is the type: callers use
|
|
51069
|
+
* `z.infer`, they do not restate the shape.
|
|
51070
|
+
*/
|
|
51071
|
+
var OverrideSourceSchema = object({
|
|
51072
|
+
addonId: string().min(1),
|
|
51073
|
+
stableId: string().min(1),
|
|
51074
|
+
cap: string().min(1),
|
|
51075
|
+
fieldPath: string().min(1)
|
|
51076
|
+
});
|
|
51077
|
+
var IdentityTransformDraftSchema = object({ kind: literal("identity") });
|
|
51078
|
+
var InvertTransformDraftSchema = object({ kind: literal("invert") });
|
|
51079
|
+
var ThresholdTransformDraftSchema = object({
|
|
51080
|
+
kind: literal("threshold"),
|
|
51081
|
+
comparison: _enum(["gte", "lte"]),
|
|
51082
|
+
threshold: number(),
|
|
51083
|
+
startDwellMs: number().nonnegative(),
|
|
51084
|
+
stopDwellMs: number().nonnegative()
|
|
51085
|
+
});
|
|
51086
|
+
var CustomizeTransformDraftSchema = discriminatedUnion("kind", [
|
|
51087
|
+
IdentityTransformDraftSchema,
|
|
51088
|
+
InvertTransformDraftSchema,
|
|
51089
|
+
ThresholdTransformDraftSchema,
|
|
51090
|
+
object({
|
|
51091
|
+
kind: literal("linear"),
|
|
51092
|
+
scale: number(),
|
|
51093
|
+
offset: number(),
|
|
51094
|
+
clampMin: number().optional(),
|
|
51095
|
+
clampMax: number().optional()
|
|
51096
|
+
}),
|
|
51097
|
+
object({
|
|
51098
|
+
kind: literal("enum-map"),
|
|
51099
|
+
mapping: record(string(), string().nullable())
|
|
51100
|
+
}),
|
|
51101
|
+
object({ kind: literal("number") })
|
|
51102
|
+
]);
|
|
51103
|
+
var ScalarOverrideDraftSchema = object({
|
|
51104
|
+
kind: literal("scalar"),
|
|
51105
|
+
cap: string().min(1),
|
|
51106
|
+
targetId: string().min(1),
|
|
51107
|
+
source: OverrideSourceSchema,
|
|
51108
|
+
transform: CustomizeTransformDraftSchema
|
|
51109
|
+
});
|
|
51110
|
+
var KeyedArrayOverrideDraftSchema = object({
|
|
51111
|
+
kind: literal("keyedArray"),
|
|
51112
|
+
cap: string().min(1),
|
|
51113
|
+
targetId: string().min(1),
|
|
51114
|
+
key: string().min(1),
|
|
51115
|
+
label: string().min(1),
|
|
51116
|
+
fieldPath: string().min(1),
|
|
51117
|
+
source: OverrideSourceSchema,
|
|
51118
|
+
transform: CustomizeTransformDraftSchema
|
|
51119
|
+
});
|
|
51120
|
+
var PulseOverrideDraftSchema = object({
|
|
51121
|
+
kind: literal("pulse"),
|
|
51122
|
+
cap: string().min(1),
|
|
51123
|
+
targetId: string().min(1),
|
|
51124
|
+
enabled: boolean(),
|
|
51125
|
+
debounceMs: number().nonnegative(),
|
|
51126
|
+
edges: array(_enum([
|
|
51127
|
+
"rising",
|
|
51128
|
+
"button",
|
|
51129
|
+
"native-event"
|
|
51130
|
+
])).min(1).optional(),
|
|
51131
|
+
sources: array(OverrideSourceSchema).min(1)
|
|
51132
|
+
});
|
|
51133
|
+
var SpanSourceDraftSchema = OverrideSourceSchema.extend({ mode: _enum([
|
|
51134
|
+
"in-addition",
|
|
51135
|
+
"confirm",
|
|
51136
|
+
"replace"
|
|
51137
|
+
]).optional() });
|
|
51138
|
+
discriminatedUnion("kind", [
|
|
51139
|
+
ScalarOverrideDraftSchema,
|
|
51140
|
+
KeyedArrayOverrideDraftSchema,
|
|
51141
|
+
PulseOverrideDraftSchema,
|
|
51142
|
+
object({
|
|
51143
|
+
kind: literal("span"),
|
|
51144
|
+
cap: string().min(1),
|
|
51145
|
+
targetId: string().min(1),
|
|
51146
|
+
timeoutMs: number().nonnegative(),
|
|
51147
|
+
cooldownMs: number().nonnegative().optional(),
|
|
51148
|
+
sources: array(SpanSourceDraftSchema)
|
|
51149
|
+
})
|
|
51150
|
+
]);
|
|
51151
|
+
object({
|
|
51152
|
+
targetId: string().min(1),
|
|
51153
|
+
configured: boolean(),
|
|
51154
|
+
source: _enum(["native", "assigned"]),
|
|
51155
|
+
state: _enum([
|
|
51156
|
+
"active",
|
|
51157
|
+
"stale",
|
|
51158
|
+
"released",
|
|
51159
|
+
"unavailable"
|
|
51160
|
+
]),
|
|
51161
|
+
reason: string().nullable()
|
|
51162
|
+
});
|
|
51163
|
+
/**
|
|
51164
|
+
* What a running-threshold proposal says (planning#405). The schema is the
|
|
51165
|
+
* type: the algorithm, the capability method and the UI all read `z.infer`.
|
|
51166
|
+
*
|
|
51167
|
+
* A proposal is read-only advice: it carries the numbers it was derived from
|
|
51168
|
+
* (`evidence`) so the operator can judge it, and an `insufficient` answer names
|
|
51169
|
+
* WHY with a typed reason and the catalog defaults, never an invented number.
|
|
51170
|
+
*/
|
|
51171
|
+
var RunningProposalTierSchema = _enum(["raw", "5m"]);
|
|
51172
|
+
var RunningProposalConfidenceSchema = _enum([
|
|
51173
|
+
"high",
|
|
51174
|
+
"medium",
|
|
51175
|
+
"low"
|
|
51176
|
+
]);
|
|
51177
|
+
var RunningProposalInsufficientReasonSchema = _enum([
|
|
51178
|
+
"no-history",
|
|
51179
|
+
"span-too-short",
|
|
51180
|
+
"truncated",
|
|
51181
|
+
"no-idle-floor",
|
|
51182
|
+
"no-runs",
|
|
51183
|
+
"no-separation"
|
|
51184
|
+
]);
|
|
51185
|
+
var RunningProposalReplaySchema = object({
|
|
51186
|
+
/** Intervals the real dwell expression held true over the window. */
|
|
51187
|
+
intervals: number().int().nonnegative(),
|
|
51188
|
+
/** Intervals outside every run, or a second interval inside one. */
|
|
51189
|
+
extra: number().int().nonnegative(),
|
|
51190
|
+
/** Runs without an interval of their own (none, or merged into a neighbour). */
|
|
51191
|
+
missed: number().int().nonnegative()
|
|
51192
|
+
});
|
|
51193
|
+
var RunningProposalEvidenceSchema = object({
|
|
51194
|
+
tier: RunningProposalTierSchema,
|
|
51195
|
+
spanMs: number().nonnegative(),
|
|
51196
|
+
from: number(),
|
|
51197
|
+
to: number(),
|
|
51198
|
+
points: number().int().nonnegative(),
|
|
51199
|
+
runsFound: number().int().nonnegative(),
|
|
51200
|
+
pausesFound: number().int().nonnegative(),
|
|
51201
|
+
longestPauseMs: number().nonnegative(),
|
|
51202
|
+
/** Episodes shorter than ~90 s (an anti-crease pulse, a display waking): never a run, never a pause. */
|
|
51203
|
+
pulsesFound: number().int().nonnegative(),
|
|
51204
|
+
longestPulseMs: number().nonnegative(),
|
|
51205
|
+
idleFloorW: number(),
|
|
51206
|
+
noiseCeilingW: number(),
|
|
51207
|
+
plateauW: number(),
|
|
51208
|
+
replay: RunningProposalReplaySchema
|
|
51209
|
+
});
|
|
51210
|
+
var RunningProposalInsufficientEvidenceSchema = object({
|
|
51211
|
+
spanMs: number().nonnegative(),
|
|
51212
|
+
points: number().int().nonnegative(),
|
|
51213
|
+
runsFound: number().int().nonnegative()
|
|
51214
|
+
});
|
|
51215
|
+
var RunningThresholdProposalSchema = discriminatedUnion("state", [object({
|
|
51216
|
+
state: literal("proposal"),
|
|
51217
|
+
transform: ThresholdTransformDraftSchema,
|
|
51218
|
+
evidence: RunningProposalEvidenceSchema,
|
|
51219
|
+
confidence: RunningProposalConfidenceSchema,
|
|
51220
|
+
/** Why the confidence is not higher; empty when nothing held it back. */
|
|
51221
|
+
notes: array(string())
|
|
51222
|
+
}), object({
|
|
51223
|
+
state: literal("insufficient"),
|
|
51224
|
+
reason: RunningProposalInsufficientReasonSchema,
|
|
51225
|
+
evidence: RunningProposalInsufficientEvidenceSchema,
|
|
51226
|
+
/** The catalog defaults, offered as what stands when nothing better is known. */
|
|
51227
|
+
fallback: ThresholdTransformDraftSchema
|
|
51228
|
+
})]);
|
|
51229
|
+
/**
|
|
50922
51230
|
* The report of a one-shot "move this owner's plaintext secrets into the
|
|
50923
51231
|
* keychain" run (D878). COUNTS only - never a value, never a ref.
|
|
50924
51232
|
*
|
|
@@ -51215,6 +51523,14 @@ method(object({}), object({ blocks: array(CoreBlockSchema) }), { auth: "admin" }
|
|
|
51215
51523
|
kind: "mutation",
|
|
51216
51524
|
auth: "admin",
|
|
51217
51525
|
access: "view"
|
|
51526
|
+
}), method(object({
|
|
51527
|
+
deviceId: number().int(),
|
|
51528
|
+
cap: string().min(1),
|
|
51529
|
+
fieldPath: string().min(1),
|
|
51530
|
+
deviceType: _enum(DeviceType).optional()
|
|
51531
|
+
}), RunningThresholdProposalSchema, {
|
|
51532
|
+
auth: "admin",
|
|
51533
|
+
access: "view"
|
|
51218
51534
|
}), method(object({
|
|
51219
51535
|
blockId: string().min(1),
|
|
51220
51536
|
trace: AutomationRunTraceSchema.optional(),
|
|
@@ -52176,7 +52492,27 @@ method(object({
|
|
|
52176
52492
|
* exposes only the COMMON surface: link state, supported device
|
|
52177
52493
|
* kinds (so the UI can filter the device picker), and per-device
|
|
52178
52494
|
* expose/unexpose.
|
|
52179
|
-
|
|
52495
|
+
*
|
|
52496
|
+
* INSTANCES. One export addon can serve several independent targets (a
|
|
52497
|
+
* HomeKit bridge, a Home Assistant broker). `listInstances` names them.
|
|
52498
|
+
* `instanceId` on a READ is optional: absent = the whole addon (linked if any
|
|
52499
|
+
* enabled instance is, `exposedDeviceCount` = distinct devices, `setup` = the
|
|
52500
|
+
* default instance's); present = that instance; an id the provider does not
|
|
52501
|
+
* serve is refused with `ExportInstanceUnknownError` (`export-instance-unknown`),
|
|
52502
|
+
* never answered empty. `instanceId` on a WRITE is REQUIRED: a membership
|
|
52503
|
+
* change always names the target it changes. A single-instance provider
|
|
52504
|
+
* accepts an absent id on a read or its own id, and refuses any other.
|
|
52505
|
+
*/
|
|
52506
|
+
/** Which instance of an export addon a call addresses. Absent on a read = the whole addon. */
|
|
52507
|
+
var InstanceIdSchema$1 = string().min(1);
|
|
52508
|
+
var InstancePinSchema = object({ instanceId: InstanceIdSchema$1.optional() });
|
|
52509
|
+
/** One independent export target of an addon. */
|
|
52510
|
+
var ExportInstanceSchema = object({
|
|
52511
|
+
instanceId: InstanceIdSchema$1,
|
|
52512
|
+
name: string(),
|
|
52513
|
+
enabled: boolean(),
|
|
52514
|
+
kind: string().optional()
|
|
52515
|
+
});
|
|
52180
52516
|
var LinkStateSchema = _enum([
|
|
52181
52517
|
"unlinked",
|
|
52182
52518
|
"linked",
|
|
@@ -52227,10 +52563,14 @@ var ExposedDeviceSchema = object({
|
|
|
52227
52563
|
capabilities: array(string()).optional()
|
|
52228
52564
|
});
|
|
52229
52565
|
var ExposeInputSchema = object({
|
|
52566
|
+
instanceId: InstanceIdSchema$1,
|
|
52230
52567
|
deviceId: string(),
|
|
52231
52568
|
capabilities: array(string()).optional()
|
|
52232
52569
|
});
|
|
52233
|
-
var UnexposeInputSchema = object({
|
|
52570
|
+
var UnexposeInputSchema = object({
|
|
52571
|
+
instanceId: InstanceIdSchema$1,
|
|
52572
|
+
deviceId: string()
|
|
52573
|
+
});
|
|
52234
52574
|
/**
|
|
52235
52575
|
* What an exporter may expose besides devices (D968). An action and a
|
|
52236
52576
|
* notification target are LIST ENTRIES, never devices (D954): they enter an
|
|
@@ -52259,15 +52599,21 @@ var ExposedEntitySchema = object({
|
|
|
52259
52599
|
entity: ExportEntityRefSchema,
|
|
52260
52600
|
exposedAs: string().optional()
|
|
52261
52601
|
});
|
|
52262
|
-
var ExposeEntityInputSchema = object({
|
|
52263
|
-
|
|
52264
|
-
|
|
52602
|
+
var ExposeEntityInputSchema = object({
|
|
52603
|
+
instanceId: InstanceIdSchema$1,
|
|
52604
|
+
entity: ExportEntityRefSchema
|
|
52605
|
+
});
|
|
52606
|
+
var UnexposeEntityInputSchema = object({
|
|
52607
|
+
instanceId: InstanceIdSchema$1,
|
|
52608
|
+
entity: ExportEntityRefSchema
|
|
52609
|
+
});
|
|
52610
|
+
method(InstancePinSchema, DeviceExportStatusSchema), method(_void(), array(ExportInstanceSchema)), method(InstancePinSchema, array(DeviceKindSchema)), method(InstancePinSchema, array(ExposedDeviceSchema)), method(ExposeInputSchema, _void(), {
|
|
52265
52611
|
kind: "mutation",
|
|
52266
52612
|
auth: "admin"
|
|
52267
52613
|
}), method(UnexposeInputSchema, _void(), {
|
|
52268
52614
|
kind: "mutation",
|
|
52269
52615
|
auth: "admin"
|
|
52270
|
-
}), optionalMethod(_void(), array(ExportEntityKindSchema)), optionalMethod(
|
|
52616
|
+
}), optionalMethod(_void(), array(ExportEntityKindSchema)), optionalMethod(InstancePinSchema, array(ExposedEntitySchema)), optionalMethod(ExposeEntityInputSchema, _void(), {
|
|
52271
52617
|
kind: "mutation",
|
|
52272
52618
|
auth: "admin"
|
|
52273
52619
|
}), optionalMethod(UnexposeEntityInputSchema, _void(), {
|
|
@@ -55912,15 +56258,15 @@ var FanPresetCaptureResultSchema = object({
|
|
|
55912
56258
|
items: array(FanCaptureItemSchema),
|
|
55913
56259
|
omitted: array(FanCaptureOmissionSchema)
|
|
55914
56260
|
});
|
|
55915
|
-
var deviceInput$
|
|
56261
|
+
var deviceInput$2 = object({ deviceId: number().int().nonnegative() });
|
|
55916
56262
|
DeviceType.Fan;
|
|
55917
|
-
method(deviceInput$
|
|
56263
|
+
method(deviceInput$2, array(FanPresetSchema), { auth: "protected" }), method(deviceInput$2.extend({ presets: array(FanPresetSchema).max(12) }), FanPresetsSetResultSchema, {
|
|
55918
56264
|
kind: "mutation",
|
|
55919
56265
|
auth: "admin"
|
|
55920
|
-
}), method(deviceInput$
|
|
56266
|
+
}), method(deviceInput$2.extend({ presetId: string().min(1) }), FanPresetApplyResultSchema, {
|
|
55921
56267
|
kind: "mutation",
|
|
55922
56268
|
auth: "protected"
|
|
55923
|
-
}), method(deviceInput$
|
|
56269
|
+
}), method(deviceInput$2.extend({
|
|
55924
56270
|
fields: array(FanCaptureFieldSchema).optional(),
|
|
55925
56271
|
steps: array(ActionStepSchema).max(20).default([])
|
|
55926
56272
|
}), FanPresetCaptureResultSchema, { auth: "protected" });
|
|
@@ -56803,6 +57149,12 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
|
|
|
56803
57149
|
}), object({ success: boolean() }), {
|
|
56804
57150
|
kind: "mutation",
|
|
56805
57151
|
auth: "admin"
|
|
57152
|
+
}), method(object({ id: string() }), object({
|
|
57153
|
+
rows: number().int().nonnegative(),
|
|
57154
|
+
secrets: number().int().nonnegative()
|
|
57155
|
+
}), {
|
|
57156
|
+
kind: "mutation",
|
|
57157
|
+
auth: "admin"
|
|
56806
57158
|
}), method(_void(), array(AvailableIntegrationTypeSchema), { auth: "admin" }), method(object({
|
|
56807
57159
|
addonId: string(),
|
|
56808
57160
|
settings: record(string(), unknown())
|
|
@@ -56831,13 +57183,65 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
|
|
|
56831
57183
|
*/
|
|
56832
57184
|
var ConfigSchemaPassthrough$3 = custom();
|
|
56833
57185
|
var IntegrationInstanceIdSchema = string().min(1);
|
|
57186
|
+
var IntegrationInstanceModeSchema = _enum(["single", "multiple"]);
|
|
57187
|
+
/**
|
|
57188
|
+
* One kind of instance a provider can create (an adapter, an account type). The sign-in and
|
|
57189
|
+
* connect fields follow the `broker` contract (`broker.cap.ts`): `signIn.basePath` is a
|
|
57190
|
+
* hub-relative route set speaking the sign-in contract, `connectPath` / `disconnectPath` open an
|
|
57191
|
+
* interactive account link (popup) and may carry `{{brokerId}}`, which the UI replaces with the
|
|
57192
|
+
* instance id.
|
|
57193
|
+
*/
|
|
57194
|
+
var IntegrationInstanceKindSchema = object({
|
|
57195
|
+
/** Stable id of the kind, sent back as `createInstance.kind`. */
|
|
57196
|
+
id: string().min(1),
|
|
57197
|
+
label: string().min(1),
|
|
57198
|
+
/** The kind signs in through a server-held interactive session. */
|
|
57199
|
+
signIn: object({
|
|
57200
|
+
basePath: string().min(1),
|
|
57201
|
+
methods: array(_enum(["device-code", "proxy"])).optional()
|
|
57202
|
+
}).optional(),
|
|
57203
|
+
/** Relative hub path to start an interactive account link of an instance of this kind. */
|
|
57204
|
+
connectPath: string().min(1).optional(),
|
|
57205
|
+
/** Relative hub path to disconnect that account. */
|
|
57206
|
+
disconnectPath: string().min(1).optional()
|
|
57207
|
+
});
|
|
56834
57208
|
var IntegrationInstanceDescriptionSchema = object({
|
|
57209
|
+
/** What the instances are for the Integrations page; see {@link IntegrationInstanceRoleSchema}. */
|
|
57210
|
+
role: _enum([
|
|
57211
|
+
"devices",
|
|
57212
|
+
"services",
|
|
57213
|
+
"both"
|
|
57214
|
+
]),
|
|
57215
|
+
/** How the devices of an instance are found; absent means `{ mode: 'none' }`. */
|
|
57216
|
+
discovery: object({
|
|
57217
|
+
mode: _enum([
|
|
57218
|
+
"none",
|
|
57219
|
+
"lan",
|
|
57220
|
+
"account"
|
|
57221
|
+
]),
|
|
57222
|
+
scopedToInstance: boolean()
|
|
57223
|
+
}).optional(),
|
|
56835
57224
|
/** `single`: at most one instance can exist (Loki). `multiple`: an account each. */
|
|
56836
|
-
instanceMode:
|
|
57225
|
+
instanceMode: IntegrationInstanceModeSchema,
|
|
56837
57226
|
/** What the instance is, for the UI (`destination`, `relay`, `account`). */
|
|
56838
57227
|
kind: string(),
|
|
56839
57228
|
/** True when `testInstance` really probes the remote. */
|
|
56840
|
-
canTest: boolean()
|
|
57229
|
+
canTest: boolean(),
|
|
57230
|
+
/**
|
|
57231
|
+
* The kinds an instance can be of. Absent or one entry: nothing to choose; more than one: the
|
|
57232
|
+
* Add flow asks which first and sends it as `createInstance.kind`.
|
|
57233
|
+
*/
|
|
57234
|
+
kinds: array(IntegrationInstanceKindSchema).optional(),
|
|
57235
|
+
/**
|
|
57236
|
+
* The provider accepts `createInstance.id` for an id that once existed (an adopted id, because
|
|
57237
|
+
* devices carry it). The UI then offers "restore under its old id" on Add. Absent means no.
|
|
57238
|
+
*/
|
|
57239
|
+
allowRestoreId: boolean().optional(),
|
|
57240
|
+
/**
|
|
57241
|
+
* `createInstance` without an `id` works: the provider mints it. Absent means the caller must
|
|
57242
|
+
* send an id (the UI then mints an opaque one).
|
|
57243
|
+
*/
|
|
57244
|
+
mintsId: boolean().optional()
|
|
56841
57245
|
});
|
|
56842
57246
|
var IntegrationInstanceStatusSchema = object({
|
|
56843
57247
|
state: _enum([
|
|
@@ -56846,7 +57250,9 @@ var IntegrationInstanceStatusSchema = object({
|
|
|
56846
57250
|
"error",
|
|
56847
57251
|
"unknown"
|
|
56848
57252
|
]),
|
|
56849
|
-
detail: string().optional()
|
|
57253
|
+
detail: string().optional(),
|
|
57254
|
+
/** A short human word for the state ("Signed in", "Token expired"); shown instead of `state`. */
|
|
57255
|
+
label: string().optional()
|
|
56850
57256
|
});
|
|
56851
57257
|
var IntegrationInstanceSchema = object({
|
|
56852
57258
|
id: IntegrationInstanceIdSchema,
|
|
@@ -56854,13 +57260,18 @@ var IntegrationInstanceSchema = object({
|
|
|
56854
57260
|
/** The addon's own rule (an URL is present, a client id is present...). */
|
|
56855
57261
|
configured: boolean(),
|
|
56856
57262
|
/**
|
|
56857
|
-
* The instance's own on/off switch (D996)
|
|
56858
|
-
*
|
|
57263
|
+
* The instance's own on/off switch (D996), derived from the record body (`enabled !== false`,
|
|
57264
|
+
* so a row written before the field existed is on). Absent when the `integrations` registry
|
|
57265
|
+
* owns the switch (`describe().role` is `devices`): read it from the registry row.
|
|
56859
57266
|
*/
|
|
56860
|
-
enabled: boolean(),
|
|
57267
|
+
enabled: boolean().optional(),
|
|
57268
|
+
/** The kind of this instance (one of `describe().kinds[].id`), when the provider has kinds. */
|
|
57269
|
+
kind: string().optional(),
|
|
56861
57270
|
/** Values for the instance form; a secret is a `SecretFieldView`, never text. */
|
|
56862
57271
|
formValues: record(string(), unknown()),
|
|
56863
|
-
status: IntegrationInstanceStatusSchema.optional()
|
|
57272
|
+
status: IntegrationInstanceStatusSchema.optional(),
|
|
57273
|
+
/** Epoch ms of the last probe of the remote that produced `status`; absent when never checked. */
|
|
57274
|
+
lastCheckedAt: number().optional()
|
|
56864
57275
|
});
|
|
56865
57276
|
var IntegrationInstancePatchSchema = object({
|
|
56866
57277
|
id: IntegrationInstanceIdSchema,
|
|
@@ -56869,8 +57280,9 @@ var IntegrationInstancePatchSchema = object({
|
|
|
56869
57280
|
values: record(string(), unknown())
|
|
56870
57281
|
});
|
|
56871
57282
|
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({
|
|
56872
|
-
id: IntegrationInstanceIdSchema,
|
|
56873
|
-
name: string().min(1)
|
|
57283
|
+
id: IntegrationInstanceIdSchema.optional(),
|
|
57284
|
+
name: string().min(1),
|
|
57285
|
+
kind: string().min(1).optional()
|
|
56874
57286
|
}), object({ id: string() }), {
|
|
56875
57287
|
kind: "mutation",
|
|
56876
57288
|
auth: "admin"
|
|
@@ -59030,6 +59442,11 @@ var LogEntrySchema = object({
|
|
|
59030
59442
|
* flight, and not asking for the next slice ends the scan.
|
|
59031
59443
|
*/
|
|
59032
59444
|
var LogReadQuerySchema = object({
|
|
59445
|
+
/**
|
|
59446
|
+
* Which destination INSTANCE answers (a destination addon may hold several records). Absent ⇒
|
|
59447
|
+
* the provider's first readable one, so a caller written before instances existed is unchanged.
|
|
59448
|
+
*/
|
|
59449
|
+
instanceId: string().min(1).max(200).optional(),
|
|
59033
59450
|
/** Correlates `cancelRead`. Caller-chosen, unique per in-flight read. */
|
|
59034
59451
|
requestId: string().min(1).max(64).optional(),
|
|
59035
59452
|
/** The device the line is about (`tags.deviceId`, numeric). */
|
|
@@ -59092,6 +59509,8 @@ var LogReadResultSchema = object({
|
|
|
59092
59509
|
/** True when `cancelRead` ended this slice early. */
|
|
59093
59510
|
cancelled: boolean().optional()
|
|
59094
59511
|
});
|
|
59512
|
+
/** Names one destination instance; absent ⇒ the provider's first readable one. */
|
|
59513
|
+
var LogInstanceSelectorSchema = object({ instanceId: string().min(1).max(200).optional() });
|
|
59095
59514
|
var LogReadCapabilitiesSchema = object({
|
|
59096
59515
|
/** False ⇒ this destination only ships lines (console, forwarder, an unconfigured Loki). */
|
|
59097
59516
|
readable: boolean(),
|
|
@@ -59110,7 +59529,7 @@ var LogReadCapabilitiesSchema = object({
|
|
|
59110
59529
|
/** How far back the store reaches, when the provider knows (days). */
|
|
59111
59530
|
retentionDays: number().nullable()
|
|
59112
59531
|
});
|
|
59113
|
-
method(LogEntrySchema, _void(), { kind: "mutation" }), optionalMethod(
|
|
59532
|
+
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() }), {
|
|
59114
59533
|
kind: "mutation",
|
|
59115
59534
|
auth: "admin"
|
|
59116
59535
|
});
|
|
@@ -59214,214 +59633,6 @@ var LoginMethodContributionSchema = discriminatedUnion("kind", [
|
|
|
59214
59633
|
]);
|
|
59215
59634
|
method(_void(), array(LoginMethodContributionSchema).readonly());
|
|
59216
59635
|
/**
|
|
59217
|
-
* Media-player cap. Models HA `media_player.*` (Sonos, Chromecast,
|
|
59218
|
-
* Apple TV, Spotify, Roku, generic OTT receivers, …) on
|
|
59219
|
-
* `DeviceType.MediaPlayer`. Disjoint from the camera streaming
|
|
59220
|
-
* surface — those use `DeviceType.Camera` + the broker pipeline.
|
|
59221
|
-
*
|
|
59222
|
-
* The cap declares a wide method surface; not every backend supports
|
|
59223
|
-
* every method. Drivers signal sub-capability via the
|
|
59224
|
-
* `DeviceFeature.MediaPlayerXxx` flags (paired one-to-one with the
|
|
59225
|
-
* corresponding method) so the UI gates buttons without a slice
|
|
59226
|
-
* fetch — same pattern as `PanTiltZoom` for cameras.
|
|
59227
|
-
*/
|
|
59228
|
-
var MediaPlayerStateSchema = _enum([
|
|
59229
|
-
"off",
|
|
59230
|
-
"on",
|
|
59231
|
-
"idle",
|
|
59232
|
-
"playing",
|
|
59233
|
-
"paused",
|
|
59234
|
-
"buffering",
|
|
59235
|
-
"standby"
|
|
59236
|
-
]);
|
|
59237
|
-
var MediaPlayerRepeatSchema = _enum([
|
|
59238
|
-
"off",
|
|
59239
|
-
"all",
|
|
59240
|
-
"one"
|
|
59241
|
-
]);
|
|
59242
|
-
var MediaInfoSchema = object({
|
|
59243
|
-
/** Free-form media kind (`music`, `tvshow`, `movie`, `app`, `channel`,
|
|
59244
|
-
* `podcast`, …). */
|
|
59245
|
-
type: string(),
|
|
59246
|
-
/** Human-readable title. */
|
|
59247
|
-
title: string(),
|
|
59248
|
-
/** Optional artist / channel / station label. */
|
|
59249
|
-
artist: string().optional(),
|
|
59250
|
-
/** Optional album / season / show name. */
|
|
59251
|
-
album: string().optional(),
|
|
59252
|
-
/** Optional cover-art / thumbnail URL. */
|
|
59253
|
-
imageUrl: string().optional()
|
|
59254
|
-
});
|
|
59255
|
-
/**
|
|
59256
|
-
* Where `state`, `volumeLevel`, `isMuted` and `source` come from. `reported`:
|
|
59257
|
-
* the device said so. `assumed`: the driver has no feedback (infrared) and
|
|
59258
|
-
* tracks what it last SENT; it moves only after a send was accepted, and a
|
|
59259
|
-
* human at the real remote makes it wrong. A UI shows an assumed value as a
|
|
59260
|
-
* guess, never as a reading.
|
|
59261
|
-
*/
|
|
59262
|
-
var MediaPlayerStateSourceSchema = _enum(["reported", "assumed"]);
|
|
59263
|
-
/** The fields of a media-player status a driver can only guess. */
|
|
59264
|
-
var MediaPlayerAssumedFieldSchema = _enum([
|
|
59265
|
-
"state",
|
|
59266
|
-
"volumeLevel",
|
|
59267
|
-
"isMuted",
|
|
59268
|
-
"source"
|
|
59269
|
-
]);
|
|
59270
|
-
var MediaPlayerStatusSchema = object({
|
|
59271
|
-
/** Playback lifecycle state. */
|
|
59272
|
-
state: MediaPlayerStateSchema,
|
|
59273
|
-
/**
|
|
59274
|
-
* Whether the state fields are readings or the driver's own bookkeeping.
|
|
59275
|
-
* A slice written before this field existed parses as `reported`.
|
|
59276
|
-
*/
|
|
59277
|
-
stateSource: MediaPlayerStateSourceSchema.default("reported"),
|
|
59278
|
-
/**
|
|
59279
|
-
* Which fields are the driver's own guess. `stateSource` is `assumed` when
|
|
59280
|
-
* this is not empty; a field not listed here is a reading even then (power
|
|
59281
|
-
* from a running-state source, mute guessed from the last send).
|
|
59282
|
-
*/
|
|
59283
|
-
assumedFields: array(MediaPlayerAssumedFieldSchema).default([]),
|
|
59284
|
-
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
59285
|
-
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
59286
|
-
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59287
|
-
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
59288
|
-
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
59289
|
-
isMuted: boolean().nullable(),
|
|
59290
|
-
/** Active source / input. Empty when no source surface. */
|
|
59291
|
-
source: string(),
|
|
59292
|
-
/** Selectable sources. Empty when no source surface.
|
|
59293
|
-
* Pair with `DeviceFeature.MediaPlayerSelectSource`. */
|
|
59294
|
-
availableSources: array(string()),
|
|
59295
|
-
/** Currently-playing media info. Null when nothing is playing. */
|
|
59296
|
-
currentMedia: MediaInfoSchema.nullable(),
|
|
59297
|
-
/** Current playback position in ms. Null when not seekable or
|
|
59298
|
-
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
59299
|
-
position: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
59300
|
-
/** Total duration of the current media in ms. Null when unknown
|
|
59301
|
-
* (live stream) or nothing is playing. */
|
|
59302
|
-
duration: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
59303
|
-
/** Shuffle toggle. Null when no shuffle surface.
|
|
59304
|
-
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
59305
|
-
shuffle: boolean().nullable(),
|
|
59306
|
-
/** Repeat mode. Null when no repeat surface.
|
|
59307
|
-
* Pair with `DeviceFeature.MediaPlayerRepeat`. */
|
|
59308
|
-
repeat: MediaPlayerRepeatSchema.nullable(),
|
|
59309
|
-
/** Ms epoch when the slice was last updated. */
|
|
59310
|
-
lastChangedAt: number()
|
|
59311
|
-
});
|
|
59312
|
-
var mediaPlayerCapability = {
|
|
59313
|
-
name: "media-player",
|
|
59314
|
-
scope: "device",
|
|
59315
|
-
deviceNative: true,
|
|
59316
|
-
mode: "singleton",
|
|
59317
|
-
deviceTypes: [DeviceType.MediaPlayer],
|
|
59318
|
-
methods: {
|
|
59319
|
-
play: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
59320
|
-
kind: "mutation",
|
|
59321
|
-
auth: "protected"
|
|
59322
|
-
}),
|
|
59323
|
-
pause: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
59324
|
-
kind: "mutation",
|
|
59325
|
-
auth: "protected"
|
|
59326
|
-
}),
|
|
59327
|
-
stop: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
59328
|
-
kind: "mutation",
|
|
59329
|
-
auth: "protected"
|
|
59330
|
-
}),
|
|
59331
|
-
next: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
59332
|
-
kind: "mutation",
|
|
59333
|
-
auth: "protected"
|
|
59334
|
-
}),
|
|
59335
|
-
previous: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
59336
|
-
kind: "mutation",
|
|
59337
|
-
auth: "protected"
|
|
59338
|
-
}),
|
|
59339
|
-
seek: method(object({
|
|
59340
|
-
deviceId: number().int().nonnegative(),
|
|
59341
|
-
position: number().int().nonnegative()
|
|
59342
|
-
}), _void(), {
|
|
59343
|
-
kind: "mutation",
|
|
59344
|
-
auth: "protected"
|
|
59345
|
-
}),
|
|
59346
|
-
setVolume: method(object({
|
|
59347
|
-
deviceId: number().int().nonnegative(),
|
|
59348
|
-
volumeLevel: number().min(0).max(100)
|
|
59349
|
-
}), _void(), {
|
|
59350
|
-
kind: "mutation",
|
|
59351
|
-
auth: "protected"
|
|
59352
|
-
}),
|
|
59353
|
-
setMute: method(object({
|
|
59354
|
-
deviceId: number().int().nonnegative(),
|
|
59355
|
-
muted: boolean()
|
|
59356
|
-
}), _void(), {
|
|
59357
|
-
kind: "mutation",
|
|
59358
|
-
auth: "protected"
|
|
59359
|
-
}),
|
|
59360
|
-
setShuffle: method(object({
|
|
59361
|
-
deviceId: number().int().nonnegative(),
|
|
59362
|
-
shuffle: boolean()
|
|
59363
|
-
}), _void(), {
|
|
59364
|
-
kind: "mutation",
|
|
59365
|
-
auth: "protected"
|
|
59366
|
-
}),
|
|
59367
|
-
setRepeat: method(object({
|
|
59368
|
-
deviceId: number().int().nonnegative(),
|
|
59369
|
-
repeat: MediaPlayerRepeatSchema
|
|
59370
|
-
}), _void(), {
|
|
59371
|
-
kind: "mutation",
|
|
59372
|
-
auth: "protected"
|
|
59373
|
-
}),
|
|
59374
|
-
selectSource: method(object({
|
|
59375
|
-
deviceId: number().int().nonnegative(),
|
|
59376
|
-
source: string().min(1)
|
|
59377
|
-
}), _void(), {
|
|
59378
|
-
kind: "mutation",
|
|
59379
|
-
auth: "protected"
|
|
59380
|
-
}),
|
|
59381
|
-
playMedia: method(object({
|
|
59382
|
-
deviceId: number().int().nonnegative(),
|
|
59383
|
-
/** Media identifier / URL. */
|
|
59384
|
-
mediaId: string().min(1),
|
|
59385
|
-
/** Media kind (`music`, `tvshow`, `movie`, `app`, …) — provider
|
|
59386
|
-
* passes it through to the upstream service. */
|
|
59387
|
-
mediaType: string().min(1)
|
|
59388
|
-
}), _void(), {
|
|
59389
|
-
kind: "mutation",
|
|
59390
|
-
auth: "protected"
|
|
59391
|
-
})
|
|
59392
|
-
},
|
|
59393
|
-
status: {
|
|
59394
|
-
schema: MediaPlayerStatusSchema,
|
|
59395
|
-
kind: "push"
|
|
59396
|
-
},
|
|
59397
|
-
/**
|
|
59398
|
-
* Runtime-state slice — mirrored by the kernel. UI players read the
|
|
59399
|
-
* full slice for live now-playing, volume, and progress updates
|
|
59400
|
-
* without polling.
|
|
59401
|
-
*/
|
|
59402
|
-
runtimeState: MediaPlayerStatusSchema,
|
|
59403
|
-
/**
|
|
59404
|
-
* Runtime-state durability: **session** — a restored transport position describes a playback that stopped when the hub did.
|
|
59405
|
-
*
|
|
59406
|
-
* See `RuntimeStateDurability`. Enforced by
|
|
59407
|
-
* `scripts/check-runtime-state-durability.ts`.
|
|
59408
|
-
*/
|
|
59409
|
-
durability: "session",
|
|
59410
|
-
/**
|
|
59411
|
-
* History (D850): volume (a level an operator or an automation sets; the
|
|
59412
|
-
* default 10 s floor folds a slider drag into its end value) and mute.
|
|
59413
|
-
* `position` is not recorded: it moves continuously while playing.
|
|
59414
|
-
*/
|
|
59415
|
-
history: { fields: {
|
|
59416
|
-
volumeLevel: {
|
|
59417
|
-
kind: "gauge",
|
|
59418
|
-
unit: "%",
|
|
59419
|
-
deadband: 1
|
|
59420
|
-
},
|
|
59421
|
-
isMuted: { kind: "boolean" }
|
|
59422
|
-
} }
|
|
59423
|
-
};
|
|
59424
|
-
/**
|
|
59425
59636
|
* mesh-network — collection cap for mesh-VPN providers.
|
|
59426
59637
|
*
|
|
59427
59638
|
* Different shape from `network-access` (public tunnels):
|
|
@@ -73505,6 +73716,14 @@ var powerMeterCapability = {
|
|
|
73505
73716
|
deviceNative: true,
|
|
73506
73717
|
mode: "singleton",
|
|
73507
73718
|
deviceTypes: POWER_METER_DEVICE_TYPES,
|
|
73719
|
+
deviceConfig: { ui: {
|
|
73720
|
+
kind: "widget",
|
|
73721
|
+
widgetId: "host/power-meter-line",
|
|
73722
|
+
tab: "power",
|
|
73723
|
+
placement: "hero",
|
|
73724
|
+
label: "Power",
|
|
73725
|
+
order: 4
|
|
73726
|
+
} },
|
|
73508
73727
|
methods: {},
|
|
73509
73728
|
status: {
|
|
73510
73729
|
schema: PowerMeterStatusSchema,
|
|
@@ -73564,6 +73783,117 @@ var powerMeterCapability = {
|
|
|
73564
73783
|
volatileStateFields: ["lastFetchedAt"],
|
|
73565
73784
|
customize: powerMeterCustomize
|
|
73566
73785
|
};
|
|
73786
|
+
var PowerSourceRefusalReasonSchema = _enum([
|
|
73787
|
+
"no-power-source",
|
|
73788
|
+
"switch-missing",
|
|
73789
|
+
"switch-offline",
|
|
73790
|
+
"switch-unknown",
|
|
73791
|
+
"restart-in-progress",
|
|
73792
|
+
"switch-call-failed"
|
|
73793
|
+
]);
|
|
73794
|
+
var PowerSourceActionResultSchema = discriminatedUnion("accepted", [object({ accepted: literal(true) }), object({
|
|
73795
|
+
accepted: literal(false),
|
|
73796
|
+
reason: PowerSourceRefusalReasonSchema,
|
|
73797
|
+
/** One line for the operator, naming the switch. */
|
|
73798
|
+
message: string()
|
|
73799
|
+
})]);
|
|
73800
|
+
var PowerSourceInfoSchema = object({
|
|
73801
|
+
/** False when the device has no power source linked; the rest is then empty. */
|
|
73802
|
+
linked: boolean(),
|
|
73803
|
+
switchDeviceId: number().nullable(),
|
|
73804
|
+
switchName: string().nullable(),
|
|
73805
|
+
/** The switch's on/off state, or null when it is unknown. Never false for unknown (D393). */
|
|
73806
|
+
switchOn: boolean().nullable(),
|
|
73807
|
+
switchOnline: boolean().nullable(),
|
|
73808
|
+
restartInProgress: boolean(),
|
|
73809
|
+
offSeconds: number().int()
|
|
73810
|
+
});
|
|
73811
|
+
/** The composed slice: the switch state the link mirrors, plus the stored off time. */
|
|
73812
|
+
var PowerSourceStateSchema = object({
|
|
73813
|
+
/** Null while the switch has not reported: unknown is never `false` (D393). */
|
|
73814
|
+
switchOn: boolean().nullable(),
|
|
73815
|
+
offSeconds: number().int(),
|
|
73816
|
+
lastFetchedAt: number()
|
|
73817
|
+
});
|
|
73818
|
+
var POWER_SOURCE_DEVICE_TYPES = [
|
|
73819
|
+
DeviceType.Gateway,
|
|
73820
|
+
DeviceType.Hub,
|
|
73821
|
+
DeviceType.Camera,
|
|
73822
|
+
DeviceType.Sensor,
|
|
73823
|
+
DeviceType.MediaPlayer,
|
|
73824
|
+
DeviceType.Vacuum,
|
|
73825
|
+
DeviceType.Generic,
|
|
73826
|
+
DeviceType.Washer,
|
|
73827
|
+
DeviceType.Dryer,
|
|
73828
|
+
DeviceType.Dishwasher,
|
|
73829
|
+
DeviceType.PetFountain,
|
|
73830
|
+
DeviceType.Fan,
|
|
73831
|
+
DeviceType.Humidifier,
|
|
73832
|
+
DeviceType.Climate,
|
|
73833
|
+
DeviceType.WaterHeater
|
|
73834
|
+
];
|
|
73835
|
+
var powerSourceCustomize = {
|
|
73836
|
+
version: 1,
|
|
73837
|
+
targets: [{
|
|
73838
|
+
id: "switch",
|
|
73839
|
+
cardinality: "scalar",
|
|
73840
|
+
vocabulary: {
|
|
73841
|
+
cap: "power-source",
|
|
73842
|
+
stateField: "switchOn"
|
|
73843
|
+
},
|
|
73844
|
+
deviceTypes: POWER_SOURCE_DEVICE_TYPES,
|
|
73845
|
+
apply: "add",
|
|
73846
|
+
path: "switchOn",
|
|
73847
|
+
sources: [{
|
|
73848
|
+
kind: "switch",
|
|
73849
|
+
transforms: [{ kind: "identity" }]
|
|
73850
|
+
}],
|
|
73851
|
+
companions: [{
|
|
73852
|
+
kind: "constant",
|
|
73853
|
+
path: "offSeconds",
|
|
73854
|
+
value: 10,
|
|
73855
|
+
when: "add"
|
|
73856
|
+
}, {
|
|
73857
|
+
kind: "clock",
|
|
73858
|
+
path: "lastFetchedAt",
|
|
73859
|
+
when: "always"
|
|
73860
|
+
}],
|
|
73861
|
+
sourceReport: { status: "assignment-status" }
|
|
73862
|
+
}]
|
|
73863
|
+
};
|
|
73864
|
+
var deviceInput$1 = object({ deviceId: number().int().nonnegative() });
|
|
73865
|
+
var powerSourceCapability = {
|
|
73866
|
+
name: "power-source",
|
|
73867
|
+
scope: "device",
|
|
73868
|
+
mode: "singleton",
|
|
73869
|
+
deviceTypes: POWER_SOURCE_DEVICE_TYPES,
|
|
73870
|
+
methods: {
|
|
73871
|
+
getStatus: systemMethod(deviceInput$1, PowerSourceInfoSchema, { auth: "admin" }),
|
|
73872
|
+
powerOn: systemMethod(deviceInput$1, PowerSourceActionResultSchema, {
|
|
73873
|
+
kind: "mutation",
|
|
73874
|
+
auth: "admin"
|
|
73875
|
+
}),
|
|
73876
|
+
powerOff: systemMethod(deviceInput$1, PowerSourceActionResultSchema, {
|
|
73877
|
+
kind: "mutation",
|
|
73878
|
+
auth: "admin"
|
|
73879
|
+
}),
|
|
73880
|
+
forceRestart: systemMethod(deviceInput$1, PowerSourceActionResultSchema, {
|
|
73881
|
+
kind: "mutation",
|
|
73882
|
+
auth: "admin"
|
|
73883
|
+
})
|
|
73884
|
+
},
|
|
73885
|
+
runtimeState: PowerSourceStateSchema,
|
|
73886
|
+
customize: powerSourceCustomize,
|
|
73887
|
+
/**
|
|
73888
|
+
* Runtime-state durability: **session** — mirrored from the linked switch on
|
|
73889
|
+
* its next report; a restored value would outlive the reading it names.
|
|
73890
|
+
*
|
|
73891
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
73892
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
73893
|
+
*/
|
|
73894
|
+
durability: "session",
|
|
73895
|
+
history: "none"
|
|
73896
|
+
};
|
|
73567
73897
|
/**
|
|
73568
73898
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
73569
73899
|
* on `DeviceType.Presence`. Read-only — no setters: presence is
|
|
@@ -77098,7 +77428,13 @@ var RemoteMediaCommandSchema = _enum([
|
|
|
77098
77428
|
"next",
|
|
77099
77429
|
"previous",
|
|
77100
77430
|
"setMute",
|
|
77101
|
-
"selectSource"
|
|
77431
|
+
"selectSource",
|
|
77432
|
+
"turnOn",
|
|
77433
|
+
"turnOff",
|
|
77434
|
+
"volumeUp",
|
|
77435
|
+
"volumeDown",
|
|
77436
|
+
"channelUp",
|
|
77437
|
+
"channelDown"
|
|
77102
77438
|
]);
|
|
77103
77439
|
/** A send result, or `not-routed`: the role is not bound, so the native cap answers. */
|
|
77104
77440
|
var RemoteMediaCommandResultSchema = discriminatedUnion("status", [...RemoteSendResultSchema.options, object({ status: literal("not-routed") })]);
|
|
@@ -77119,7 +77455,7 @@ method(deviceInput, RemoteConfigSchema, { auth: "admin" }), method(deviceInput.e
|
|
|
77119
77455
|
}), RemoteSendResultSchema, {
|
|
77120
77456
|
kind: "mutation",
|
|
77121
77457
|
auth: "protected"
|
|
77122
|
-
}), method(deviceInput.extend({
|
|
77458
|
+
}), method(deviceInput, MediaPlayerStatusSchema.nullable(), { auth: "protected" }), method(deviceInput.extend({
|
|
77123
77459
|
command: RemoteMediaCommandSchema,
|
|
77124
77460
|
muted: boolean().optional(),
|
|
77125
77461
|
source: string().optional(),
|
|
@@ -79403,7 +79739,11 @@ listSignals: method(_void(), array(StreamSignalSchema).readonly()) }
|
|
|
79403
79739
|
* `getSettingsUISchema()` surface.
|
|
79404
79740
|
*/
|
|
79405
79741
|
var SwitchStatusSchema = object({
|
|
79406
|
-
|
|
79742
|
+
/**
|
|
79743
|
+
* `null` = the device has never reported its state (a measurement that
|
|
79744
|
+
* has not happened is unknown, never `false`).
|
|
79745
|
+
*/
|
|
79746
|
+
on: boolean().nullable().meta({ label: "On" }),
|
|
79407
79747
|
/** Ms epoch of the last state change. Useful for UI "X minutes ago". */
|
|
79408
79748
|
lastChangedAt: number()
|
|
79409
79749
|
});
|
|
@@ -79428,7 +79768,7 @@ var switchCapability = {
|
|
|
79428
79768
|
}) },
|
|
79429
79769
|
events: { onStateChanged: { data: object({
|
|
79430
79770
|
deviceId: number(),
|
|
79431
|
-
on: boolean(),
|
|
79771
|
+
on: boolean().nullable(),
|
|
79432
79772
|
lastChangedAt: number()
|
|
79433
79773
|
}) } },
|
|
79434
79774
|
status: {
|
|
@@ -83031,6 +83371,26 @@ function buildEventKindDescriptor(kind, source) {
|
|
|
83031
83371
|
}
|
|
83032
83372
|
};
|
|
83033
83373
|
}
|
|
83374
|
+
/**
|
|
83375
|
+
* What a remote key is CALLED and what it LOOKS like, for every role (D963),
|
|
83376
|
+
* shared by the admin UI and the viewer. A role is data on the wire; each
|
|
83377
|
+
* client resolves its name from `label` (English and Italian side by side) and
|
|
83378
|
+
* its glyph from `icon`, a lucide id from the shared icon catalogue — the
|
|
83379
|
+
* server sends an id, a client maps it to its own icon set.
|
|
83380
|
+
*
|
|
83381
|
+
* `legend` is text printed on the key INSTEAD of a glyph (a digit has no
|
|
83382
|
+
* pictogram): a client that can draw text shows it, one that cannot falls back
|
|
83383
|
+
* to `icon`.
|
|
83384
|
+
*/
|
|
83385
|
+
function digit(n) {
|
|
83386
|
+
return {
|
|
83387
|
+
label: t(n, n),
|
|
83388
|
+
icon: "hash",
|
|
83389
|
+
legend: n
|
|
83390
|
+
};
|
|
83391
|
+
}
|
|
83392
|
+
digit("0"), digit("1"), digit("2"), digit("3"), digit("4"), digit("5"), digit("6"), digit("7"), digit("8"), digit("9");
|
|
83393
|
+
DeviceFeature.MediaPlayerPower, DeviceFeature.MediaPlayerVolumeStep, DeviceFeature.MediaPlayerChannelStep, DeviceFeature.MediaPlayerMute, DeviceFeature.MediaPlayerStop, DeviceFeature.MediaPlayerNext, DeviceFeature.MediaPlayerPrevious;
|
|
83034
83394
|
var btn = (idSuffix, row, col, init) => ({
|
|
83035
83395
|
idSuffix,
|
|
83036
83396
|
row,
|
|
@@ -83157,6 +83517,42 @@ discriminatedUnion("kind", [object({
|
|
|
83157
83517
|
kind: literal("pronto"),
|
|
83158
83518
|
code: string()
|
|
83159
83519
|
})]);
|
|
83520
|
+
/**
|
|
83521
|
+
* Propose a running threshold from a device's own power history (planning#405).
|
|
83522
|
+
*
|
|
83523
|
+
* Pure and deterministic: the same series gives the same answer. The series is
|
|
83524
|
+
* a HELD-VALUE step series — a point's value stands until the next point — which
|
|
83525
|
+
* is how device-history stores a gauge, so "time at a level" is exact, not a
|
|
83526
|
+
* count of samples.
|
|
83527
|
+
*
|
|
83528
|
+
* 1. idle floor F = time-weighted median; noise ceiling N = highest value seen
|
|
83529
|
+
* near F. A device that is not near one level most of the time has no floor.
|
|
83530
|
+
* 2. coarse activity = above max(2N, N + 5 W); consecutive stretches are episodes.
|
|
83531
|
+
* 3. an episode shorter than `PULSE_MAX_MS` is a PULSE (an anti-crease tumble, a
|
|
83532
|
+
* display waking): it is neither a run nor a pause. Among the remaining
|
|
83533
|
+
* episodes, gaps over `PAUSE_MAX_MS` always separate runs; the rest split in
|
|
83534
|
+
* two by the largest log-scale jump (>= 3x): the short ones are pauses INSIDE
|
|
83535
|
+
* a run (a soak), the long ones separate runs. A stretch under `MIN_RUN_MS`
|
|
83536
|
+
* is no run.
|
|
83537
|
+
* 4. T = geometric mean of N and the plateau's 10th percentile, snapped to a
|
|
83538
|
+
* grid a person would type; stop dwell covers the longest pause and the
|
|
83539
|
+
* kind's floor; start dwell covers the longest pulse and standby blip above T.
|
|
83540
|
+
* 5. the numbers are proved by REPLAY through the real `dwell` evaluation: each
|
|
83541
|
+
* run must hold exactly one true interval and nothing may flap outside.
|
|
83542
|
+
*/
|
|
83543
|
+
var SECOND_MS = 1e3;
|
|
83544
|
+
var MINUTE_MS$1 = 60 * SECOND_MS;
|
|
83545
|
+
24 * (60 * MINUTE_MS$1);
|
|
83546
|
+
10 * MINUTE_MS$1;
|
|
83547
|
+
30 * SECOND_MS;
|
|
83548
|
+
60 * SECOND_MS;
|
|
83549
|
+
20 * MINUTE_MS$1;
|
|
83550
|
+
90 * SECOND_MS;
|
|
83551
|
+
30 * MINUTE_MS$1;
|
|
83552
|
+
10 * MINUTE_MS$1;
|
|
83553
|
+
DeviceType.Dryer, 3 * MINUTE_MS$1, DeviceType.Dishwasher, 3 * MINUTE_MS$1, DeviceType.Washer, 10 * MINUTE_MS$1;
|
|
83554
|
+
10 * SECOND_MS;
|
|
83555
|
+
10 * SECOND_MS;
|
|
83160
83556
|
DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverStoppable, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
|
|
83161
83557
|
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
83162
83558
|
String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
|
|
@@ -85821,6 +86217,13 @@ Object.freeze({
|
|
|
85821
86217
|
access: "create",
|
|
85822
86218
|
role: "admin"
|
|
85823
86219
|
},
|
|
86220
|
+
"coreBlocks.proposeRunningThreshold": {
|
|
86221
|
+
capName: "core-blocks",
|
|
86222
|
+
capScope: "system",
|
|
86223
|
+
addonId: null,
|
|
86224
|
+
access: "view",
|
|
86225
|
+
role: "admin"
|
|
86226
|
+
},
|
|
85824
86227
|
"coreBlocks.reportAutomationRun": {
|
|
85825
86228
|
capName: "core-blocks",
|
|
85826
86229
|
capScope: "system",
|
|
@@ -86332,6 +86735,13 @@ Object.freeze({
|
|
|
86332
86735
|
access: "view",
|
|
86333
86736
|
role: "admin"
|
|
86334
86737
|
},
|
|
86738
|
+
"deviceExport.listInstances": {
|
|
86739
|
+
capName: "device-export",
|
|
86740
|
+
capScope: "system",
|
|
86741
|
+
addonId: null,
|
|
86742
|
+
access: "view",
|
|
86743
|
+
role: "admin"
|
|
86744
|
+
},
|
|
86335
86745
|
"deviceExport.listSupportedDeviceKinds": {
|
|
86336
86746
|
capName: "device-export",
|
|
86337
86747
|
capScope: "system",
|
|
@@ -87984,6 +88394,13 @@ Object.freeze({
|
|
|
87984
88394
|
access: "create",
|
|
87985
88395
|
role: "admin"
|
|
87986
88396
|
},
|
|
88397
|
+
"integrations.clearSettings": {
|
|
88398
|
+
capName: "integrations",
|
|
88399
|
+
capScope: "system",
|
|
88400
|
+
addonId: null,
|
|
88401
|
+
access: "delete",
|
|
88402
|
+
role: "admin"
|
|
88403
|
+
},
|
|
87987
88404
|
"integrations.create": {
|
|
87988
88405
|
capName: "integrations",
|
|
87989
88406
|
capScope: "system",
|
|
@@ -88768,6 +89185,20 @@ Object.freeze({
|
|
|
88768
89185
|
access: "view",
|
|
88769
89186
|
role: "admin"
|
|
88770
89187
|
},
|
|
89188
|
+
"mediaPlayer.channelDown": {
|
|
89189
|
+
capName: "media-player",
|
|
89190
|
+
capScope: "device",
|
|
89191
|
+
addonId: null,
|
|
89192
|
+
access: "create",
|
|
89193
|
+
role: "viewer"
|
|
89194
|
+
},
|
|
89195
|
+
"mediaPlayer.channelUp": {
|
|
89196
|
+
capName: "media-player",
|
|
89197
|
+
capScope: "device",
|
|
89198
|
+
addonId: null,
|
|
89199
|
+
access: "create",
|
|
89200
|
+
role: "viewer"
|
|
89201
|
+
},
|
|
88771
89202
|
"mediaPlayer.getStatus": {
|
|
88772
89203
|
capName: "media-player",
|
|
88773
89204
|
capScope: "device",
|
|
@@ -88859,6 +89290,34 @@ Object.freeze({
|
|
|
88859
89290
|
access: "create",
|
|
88860
89291
|
role: "viewer"
|
|
88861
89292
|
},
|
|
89293
|
+
"mediaPlayer.turnOff": {
|
|
89294
|
+
capName: "media-player",
|
|
89295
|
+
capScope: "device",
|
|
89296
|
+
addonId: null,
|
|
89297
|
+
access: "create",
|
|
89298
|
+
role: "viewer"
|
|
89299
|
+
},
|
|
89300
|
+
"mediaPlayer.turnOn": {
|
|
89301
|
+
capName: "media-player",
|
|
89302
|
+
capScope: "device",
|
|
89303
|
+
addonId: null,
|
|
89304
|
+
access: "create",
|
|
89305
|
+
role: "viewer"
|
|
89306
|
+
},
|
|
89307
|
+
"mediaPlayer.volumeDown": {
|
|
89308
|
+
capName: "media-player",
|
|
89309
|
+
capScope: "device",
|
|
89310
|
+
addonId: null,
|
|
89311
|
+
access: "create",
|
|
89312
|
+
role: "viewer"
|
|
89313
|
+
},
|
|
89314
|
+
"mediaPlayer.volumeUp": {
|
|
89315
|
+
capName: "media-player",
|
|
89316
|
+
capScope: "device",
|
|
89317
|
+
addonId: null,
|
|
89318
|
+
access: "create",
|
|
89319
|
+
role: "viewer"
|
|
89320
|
+
},
|
|
88862
89321
|
"meshNetwork.getStatus": {
|
|
88863
89322
|
capName: "mesh-network",
|
|
88864
89323
|
capScope: "system",
|
|
@@ -92415,6 +92874,13 @@ Object.freeze({
|
|
|
92415
92874
|
access: "create",
|
|
92416
92875
|
role: "admin"
|
|
92417
92876
|
},
|
|
92877
|
+
"remote.getAssumedStatus": {
|
|
92878
|
+
capName: "remote",
|
|
92879
|
+
capScope: "system",
|
|
92880
|
+
addonId: null,
|
|
92881
|
+
access: "view",
|
|
92882
|
+
role: "admin"
|
|
92883
|
+
},
|
|
92418
92884
|
"remote.getConfig": {
|
|
92419
92885
|
capName: "remote",
|
|
92420
92886
|
capScope: "system",
|
|
@@ -95230,6 +95696,11 @@ Object.freeze({
|
|
|
95230
95696
|
form: "single",
|
|
95231
95697
|
optional: false
|
|
95232
95698
|
}],
|
|
95699
|
+
"coreBlocks.proposeRunningThreshold": [{
|
|
95700
|
+
name: "deviceId",
|
|
95701
|
+
form: "single",
|
|
95702
|
+
optional: false
|
|
95703
|
+
}],
|
|
95233
95704
|
"cover.close": [{
|
|
95234
95705
|
name: "deviceId",
|
|
95235
95706
|
form: "single",
|
|
@@ -96081,6 +96552,16 @@ Object.freeze({
|
|
|
96081
96552
|
form: "single",
|
|
96082
96553
|
optional: true
|
|
96083
96554
|
}],
|
|
96555
|
+
"mediaPlayer.channelDown": [{
|
|
96556
|
+
name: "deviceId",
|
|
96557
|
+
form: "single",
|
|
96558
|
+
optional: false
|
|
96559
|
+
}],
|
|
96560
|
+
"mediaPlayer.channelUp": [{
|
|
96561
|
+
name: "deviceId",
|
|
96562
|
+
form: "single",
|
|
96563
|
+
optional: false
|
|
96564
|
+
}],
|
|
96084
96565
|
"mediaPlayer.getStatus": [{
|
|
96085
96566
|
name: "deviceId",
|
|
96086
96567
|
form: "single",
|
|
@@ -96146,6 +96627,26 @@ Object.freeze({
|
|
|
96146
96627
|
form: "single",
|
|
96147
96628
|
optional: false
|
|
96148
96629
|
}],
|
|
96630
|
+
"mediaPlayer.turnOff": [{
|
|
96631
|
+
name: "deviceId",
|
|
96632
|
+
form: "single",
|
|
96633
|
+
optional: false
|
|
96634
|
+
}],
|
|
96635
|
+
"mediaPlayer.turnOn": [{
|
|
96636
|
+
name: "deviceId",
|
|
96637
|
+
form: "single",
|
|
96638
|
+
optional: false
|
|
96639
|
+
}],
|
|
96640
|
+
"mediaPlayer.volumeDown": [{
|
|
96641
|
+
name: "deviceId",
|
|
96642
|
+
form: "single",
|
|
96643
|
+
optional: false
|
|
96644
|
+
}],
|
|
96645
|
+
"mediaPlayer.volumeUp": [{
|
|
96646
|
+
name: "deviceId",
|
|
96647
|
+
form: "single",
|
|
96648
|
+
optional: false
|
|
96649
|
+
}],
|
|
96149
96650
|
"meter.getStatus": [{
|
|
96150
96651
|
name: "deviceId",
|
|
96151
96652
|
form: "single",
|
|
@@ -97311,6 +97812,11 @@ Object.freeze({
|
|
|
97311
97812
|
form: "single",
|
|
97312
97813
|
optional: true
|
|
97313
97814
|
}],
|
|
97815
|
+
"remote.getAssumedStatus": [{
|
|
97816
|
+
name: "deviceId",
|
|
97817
|
+
form: "single",
|
|
97818
|
+
optional: false
|
|
97819
|
+
}],
|
|
97314
97820
|
"remote.getConfig": [{
|
|
97315
97821
|
name: "deviceId",
|
|
97316
97822
|
form: "single",
|
|
@@ -97955,99 +98461,6 @@ var BucketAccumulator = class {
|
|
|
97955
98461
|
return n;
|
|
97956
98462
|
}
|
|
97957
98463
|
};
|
|
97958
|
-
/**
|
|
97959
|
-
* A saved Customize assignment (D936). The schema is the type: callers use
|
|
97960
|
-
* `z.infer`, they do not restate the shape.
|
|
97961
|
-
*/
|
|
97962
|
-
var OverrideSourceSchema = object({
|
|
97963
|
-
addonId: string().min(1),
|
|
97964
|
-
stableId: string().min(1),
|
|
97965
|
-
cap: string().min(1),
|
|
97966
|
-
fieldPath: string().min(1)
|
|
97967
|
-
});
|
|
97968
|
-
var CustomizeTransformDraftSchema = discriminatedUnion("kind", [
|
|
97969
|
-
object({ kind: literal("identity") }),
|
|
97970
|
-
object({ kind: literal("invert") }),
|
|
97971
|
-
object({
|
|
97972
|
-
kind: literal("threshold"),
|
|
97973
|
-
comparison: _enum(["gte", "lte"]),
|
|
97974
|
-
threshold: number(),
|
|
97975
|
-
startDwellMs: number().nonnegative(),
|
|
97976
|
-
stopDwellMs: number().nonnegative()
|
|
97977
|
-
}),
|
|
97978
|
-
object({
|
|
97979
|
-
kind: literal("linear"),
|
|
97980
|
-
scale: number(),
|
|
97981
|
-
offset: number(),
|
|
97982
|
-
clampMin: number().optional(),
|
|
97983
|
-
clampMax: number().optional()
|
|
97984
|
-
}),
|
|
97985
|
-
object({
|
|
97986
|
-
kind: literal("enum-map"),
|
|
97987
|
-
mapping: record(string(), string().nullable())
|
|
97988
|
-
}),
|
|
97989
|
-
object({ kind: literal("number") })
|
|
97990
|
-
]);
|
|
97991
|
-
var ScalarOverrideDraftSchema = object({
|
|
97992
|
-
kind: literal("scalar"),
|
|
97993
|
-
cap: string().min(1),
|
|
97994
|
-
targetId: string().min(1),
|
|
97995
|
-
source: OverrideSourceSchema,
|
|
97996
|
-
transform: CustomizeTransformDraftSchema
|
|
97997
|
-
});
|
|
97998
|
-
var KeyedArrayOverrideDraftSchema = object({
|
|
97999
|
-
kind: literal("keyedArray"),
|
|
98000
|
-
cap: string().min(1),
|
|
98001
|
-
targetId: string().min(1),
|
|
98002
|
-
key: string().min(1),
|
|
98003
|
-
label: string().min(1),
|
|
98004
|
-
fieldPath: string().min(1),
|
|
98005
|
-
source: OverrideSourceSchema,
|
|
98006
|
-
transform: CustomizeTransformDraftSchema
|
|
98007
|
-
});
|
|
98008
|
-
var PulseOverrideDraftSchema = object({
|
|
98009
|
-
kind: literal("pulse"),
|
|
98010
|
-
cap: string().min(1),
|
|
98011
|
-
targetId: string().min(1),
|
|
98012
|
-
enabled: boolean(),
|
|
98013
|
-
debounceMs: number().nonnegative(),
|
|
98014
|
-
edges: array(_enum([
|
|
98015
|
-
"rising",
|
|
98016
|
-
"button",
|
|
98017
|
-
"native-event"
|
|
98018
|
-
])).min(1).optional(),
|
|
98019
|
-
sources: array(OverrideSourceSchema).min(1)
|
|
98020
|
-
});
|
|
98021
|
-
var SpanSourceDraftSchema = OverrideSourceSchema.extend({ mode: _enum([
|
|
98022
|
-
"in-addition",
|
|
98023
|
-
"confirm",
|
|
98024
|
-
"replace"
|
|
98025
|
-
]).optional() });
|
|
98026
|
-
discriminatedUnion("kind", [
|
|
98027
|
-
ScalarOverrideDraftSchema,
|
|
98028
|
-
KeyedArrayOverrideDraftSchema,
|
|
98029
|
-
PulseOverrideDraftSchema,
|
|
98030
|
-
object({
|
|
98031
|
-
kind: literal("span"),
|
|
98032
|
-
cap: string().min(1),
|
|
98033
|
-
targetId: string().min(1),
|
|
98034
|
-
timeoutMs: number().nonnegative(),
|
|
98035
|
-
cooldownMs: number().nonnegative().optional(),
|
|
98036
|
-
sources: array(SpanSourceDraftSchema)
|
|
98037
|
-
})
|
|
98038
|
-
]);
|
|
98039
|
-
object({
|
|
98040
|
-
targetId: string().min(1),
|
|
98041
|
-
configured: boolean(),
|
|
98042
|
-
source: _enum(["native", "assigned"]),
|
|
98043
|
-
state: _enum([
|
|
98044
|
-
"active",
|
|
98045
|
-
"stale",
|
|
98046
|
-
"released",
|
|
98047
|
-
"unavailable"
|
|
98048
|
-
]),
|
|
98049
|
-
reason: string().nullable()
|
|
98050
|
-
});
|
|
98051
98464
|
var G711_SCALE_CORRECTION_DB = {
|
|
98052
98465
|
PCMU: 20 * Math.log10(4),
|
|
98053
98466
|
PCMA: 20 * Math.log10(8)
|